module ActiveRecord class AdvisoryLockBase < ActiveRecord::Base def self._internal?: () -> ::TrueClass end end module ActiveRecord # See ActiveRecord::Aggregations::ClassMethods for documentation module Aggregations def initialize_dup: () -> untyped def reload: () -> untyped def clear_aggregation_cache: () -> untyped def init_internals: () -> untyped # 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 http://c2.com/cgi/wiki?ValueObject and on the dangers of not # keeping value objects immutable on http://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 (http://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")) # module ClassMethods # 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) } # def composed_of: (untyped part_id, ?::Hash[untyped, untyped] options) -> untyped def reader_method: (untyped name, untyped class_name, untyped mapping, untyped allow_nil, untyped constructor) -> untyped def writer_method: (untyped name, untyped class_name, untyped mapping, untyped allow_nil, untyped converter) -> untyped end end end module ActiveRecord class AssociationRelation < Relation def initialize: (untyped klass, untyped association) -> untyped def proxy_association: () -> untyped def ==: (untyped other) -> untyped def build: (?untyped? attributes) { () -> untyped } -> untyped def create: (?untyped? attributes) { () -> untyped } -> untyped def create!: (?untyped? attributes) { () -> untyped } -> untyped def exec_queries: () { (untyped) -> untyped } -> untyped end end module ActiveRecord module Associations class AliasTracker # Keeps track of table aliases for ActiveRecord::Associations::JoinDependency # :nodoc: def self.create: (untyped connection, untyped initial_table, untyped joins) -> untyped def self.initial_count_for: (untyped connection, untyped name, untyped table_joins) -> untyped # table_joins is an array of arel joins which might conflict with the aliases we assign here def initialize: (untyped connection, untyped aliases) -> untyped def aliased_table_for: (untyped table_name, untyped aliased_name, untyped type_caster) -> untyped attr_reader aliases: untyped def truncate: (untyped name) -> untyped end end end module ActiveRecord module Associations class Association # = Active Record Associations # # This is the root class of all associations ('+ Foo' signifies an included module Foo): # # Association # SingularAssociation # HasOneAssociation + ForeignAssociation # HasOneThroughAssociation + ThroughAssociation # BelongsToAssociation # BelongsToPolymorphicAssociation # CollectionAssociation # HasManyAssociation + ForeignAssociation # HasManyThroughAssociation + ThroughAssociation # # Associations in Active Record are middlemen between the object that # holds the association, known as the owner, and the associated # result set, known as the target. Association metadata is available in # reflection, which is an instance of ActiveRecord::Reflection::AssociationReflection. # # For example, given # # class Blog < ActiveRecord::Base # has_many :posts # end # # blog = Blog.first # # The association of blog.posts has the object +blog+ as its # owner, the collection of its posts as target, and # the reflection object represents a :has_many macro. # nodoc: attr_reader owner: untyped # = Active Record Associations # # This is the root class of all associations ('+ Foo' signifies an included module Foo): # # Association # SingularAssociation # HasOneAssociation + ForeignAssociation # HasOneThroughAssociation + ThroughAssociation # BelongsToAssociation # BelongsToPolymorphicAssociation # CollectionAssociation # HasManyAssociation + ForeignAssociation # HasManyThroughAssociation + ThroughAssociation # # Associations in Active Record are middlemen between the object that # holds the association, known as the owner, and the associated # result set, known as the target. Association metadata is available in # reflection, which is an instance of ActiveRecord::Reflection::AssociationReflection. # # For example, given # # class Blog < ActiveRecord::Base # has_many :posts # end # # blog = Blog.first # # The association of blog.posts has the object +blog+ as its # owner, the collection of its posts as target, and # the reflection object represents a :has_many macro. # nodoc: attr_reader target: untyped # = Active Record Associations # # This is the root class of all associations ('+ Foo' signifies an included module Foo): # # Association # SingularAssociation # HasOneAssociation + ForeignAssociation # HasOneThroughAssociation + ThroughAssociation # BelongsToAssociation # BelongsToPolymorphicAssociation # CollectionAssociation # HasManyAssociation + ForeignAssociation # HasManyThroughAssociation + ThroughAssociation # # Associations in Active Record are middlemen between the object that # holds the association, known as the owner, and the associated # result set, known as the target. Association metadata is available in # reflection, which is an instance of ActiveRecord::Reflection::AssociationReflection. # # For example, given # # class Blog < ActiveRecord::Base # has_many :posts # end # # blog = Blog.first # # The association of blog.posts has the object +blog+ as its # owner, the collection of its posts as target, and # the reflection object represents a :has_many macro. # nodoc: attr_reader reflection: untyped def initialize: (untyped owner, untyped reflection) -> untyped # Resets the \loaded flag to +false+ and sets the \target to +nil+. def reset: () -> untyped # Reloads the \target and returns +self+ on success. # The QueryCache is cleared if +force+ is true. def reload: (?bool force) -> untyped # Has the \target been already \loaded? def loaded?: () -> untyped # Asserts the \target has been loaded setting the \loaded flag to +true+. def loaded!: () -> untyped # The target is stale if the target no longer points to the record(s) that the # relevant foreign_key(s) refers to. If stale, the association accessor method # on the owner will reload the target. It's up to subclasses to implement the # stale_state method if relevant. # # Note that if the target has not been loaded, it is not considered stale. def stale_target?: () -> untyped # Sets the target of this association to \target, and the \loaded flag to +true+. def target=: (untyped target) -> untyped def scope: () -> untyped def reset_scope: () -> untyped # Set the inverse association, if possible def set_inverse_instance: (untyped record) -> untyped def set_inverse_instance_from_queries: (untyped record) -> untyped # Remove the inverse association, if possible def remove_inverse_instance: (untyped record) -> untyped def inversed_from: (untyped record) -> untyped # Returns the class of the target. belongs_to polymorphic overrides this to look at the # polymorphic_type field on the owner. def klass: () -> untyped def extensions: () -> untyped # Loads the \target if needed and returns it. # # This method is abstract in the sense that it relies on +find_target+, # which is expected to be provided by descendants. # # If the \target is already \loaded it is just returned. Thus, you can call # +load_target+ unconditionally to get the \target. # # ActiveRecord::RecordNotFound is rescued within the method, and it is # not reraised. The proxy is \reset and +nil+ is the return value. def load_target: () -> untyped # We can't dump @reflection and @through_reflection since it contains the scope proc def marshal_dump: () -> ::Array[untyped] def marshal_load: (untyped data) -> untyped def initialize_attributes: (untyped record, ?untyped? except_from_scope_attributes) -> untyped def create: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped def create!: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped def find_target: () -> untyped # The scope for this association. # # Note that the association_scope is merged into the target_scope only when the # scope method is called. This is because at that point the call may be surrounded # by scope.scoping { ... } or unscoped { ... } etc, which affects the scope which # actually gets built. def association_scope: () -> untyped # Can be overridden (i.e. in ThroughAssociation) to merge in other scopes (i.e. the # through association's scope) def target_scope: () -> untyped def scope_for_create: () -> untyped def find_target?: () -> untyped def creation_attributes: () -> untyped # Sets the owner attributes on the given record def set_owner_attributes: (untyped record) -> untyped # Returns true if there is a foreign key present on the owner which # references the target. This is used to determine whether we can load # the target if the owner is currently a new record (and therefore # without a key). If the owner is a new record then foreign_key must # be present in order to load target. # # Currently implemented by belongs_to (vanilla and polymorphic) and # has_one/has_many :through associations which go through a belongs_to. def foreign_key_present?: () -> ::FalseClass # Raises ActiveRecord::AssociationTypeMismatch unless +record+ is of # the kind of the class of the associated objects. Meant to be used as # a sanity check when you are about to assign an associated record. def raise_on_type_mismatch!: (untyped record) -> untyped def inverse_association_for: (untyped record) -> untyped # Can be redefined by subclasses, notably polymorphic belongs_to # The record parameter is necessary to support polymorphic inverses as we must check for # the association in the specific class of the record. def inverse_reflection_for: (untyped record) -> untyped # Returns true if inverse association on the given record needs to be set. # This method is redefined by subclasses. def invertible_for?: (untyped record) -> untyped # Returns true if record contains the foreign_key def foreign_key_for?: (untyped record) -> untyped # This should be implemented to return the values of the relevant key(s) on the owner, # so that when stale_state is different from the value stored on the last find_target, # the target is stale. # # This is only relevant to certain associations, which is why it returns +nil+ by default. def stale_state: () -> nil def build_record: (untyped attributes) { (untyped) -> untyped } -> untyped # Returns true if statement cache should be skipped on the association reader. def skip_statement_cache?: (untyped scope) -> untyped end end end module ActiveRecord module Associations class AssociationScope # nodoc: def self.scope: (untyped association) -> untyped def self.create: () { () -> untyped } -> untyped def initialize: (untyped value_transformation) -> untyped INSTANCE: untyped def scope: (untyped association) -> untyped def self.get_bind_values: (untyped owner, untyped chain) -> untyped attr_reader value_transformation: untyped def join: (untyped table, untyped constraint) -> untyped def last_chain_scope: (untyped scope, untyped reflection, untyped owner) -> untyped def transform_value: (untyped value) -> untyped def next_chain_scope: (untyped scope, untyped reflection, untyped next_reflection) -> untyped class ReflectionProxy < SimpleDelegator # :nodoc: attr_reader aliased_table: untyped def initialize: (untyped reflection, untyped aliased_table) -> untyped def all_includes: () -> nil end def get_chain: (untyped reflection, untyped association, untyped tracker) -> untyped def add_constraints: (untyped scope, untyped owner, untyped chain) -> untyped def apply_scope: (untyped scope, untyped table, untyped key, untyped value) -> untyped def eval_scope: (untyped reflection, untyped scope, untyped owner) -> untyped end end end module ActiveRecord module Associations class BelongsToAssociation < SingularAssociation # = Active Record Belongs To Association # nodoc: def handle_dependency: () -> (nil | untyped) def inversed_from: (untyped record) -> untyped def default: () { () -> untyped } -> untyped def reset: () -> untyped def updated?: () -> untyped def decrement_counters: () -> untyped def increment_counters: () -> untyped def decrement_counters_before_last_save: () -> untyped def target_changed?: () -> untyped def replace: (untyped record) -> untyped def update_counters: (untyped by) -> untyped def update_counters_via_scope: (untyped klass, untyped foreign_key, untyped by) -> untyped def find_target?: () -> untyped def require_counter_update?: () -> untyped def replace_keys: (untyped record) -> untyped def primary_key: (untyped klass) -> untyped def foreign_key_present?: () -> untyped # NOTE - for now, we're only supporting inverse setting from belongs_to back onto # has_one associations. def invertible_for?: (untyped record) -> untyped def stale_state: () -> untyped end end end module ActiveRecord module Associations class BelongsToPolymorphicAssociation < BelongsToAssociation # = Active Record Belongs To Polymorphic Association # nodoc: def klass: () -> untyped def target_changed?: () -> untyped def replace_keys: (untyped record) -> untyped def inverse_reflection_for: (untyped record) -> untyped def raise_on_type_mismatch!: (untyped record) -> nil def stale_state: () -> untyped end end end module ActiveRecord::Associations::Builder class Association attr_accessor extensions: untyped VALID_OPTIONS: ::Array[untyped] def self.build: (untyped model, untyped name, untyped scope, untyped options) { () -> untyped } -> untyped def self.create_reflection: (untyped model, untyped name, untyped scope, untyped options) { () -> untyped } -> untyped def self.build_scope: (untyped scope) -> untyped def self.macro: () -> untyped def self.valid_options: (untyped options) -> untyped def self.validate_options: (untyped options) -> untyped def self.define_extensions: (untyped model, untyped name) -> nil def self.define_callbacks: (untyped model, untyped reflection) -> untyped # Defines the setter and getter methods for the association # class Post < ActiveRecord::Base # has_many :comments # end # # Post.first.comments and Post.first.comments= methods are defined by this method... def self.define_accessors: (untyped model, untyped reflection) -> untyped def self.define_readers: (untyped mixin, untyped name) -> untyped def self.define_writers: (untyped mixin, untyped name) -> untyped def self.define_validations: (untyped model, untyped reflection) -> nil def self.valid_dependent_options: () -> untyped def self.check_dependent_options: (untyped dependent) -> untyped def self.add_destroy_callbacks: (untyped model, untyped reflection) -> untyped end end module ActiveRecord::Associations::Builder class BelongsTo < SingularAssociation # :nodoc: # nodoc: def self.macro: () -> :belongs_to def self.valid_options: (untyped options) -> untyped def self.valid_dependent_options: () -> ::Array[:destroy | :delete] def self.define_callbacks: (untyped model, untyped reflection) -> untyped def self.add_counter_cache_callbacks: (untyped model, untyped reflection) -> untyped def self.touch_record: (untyped o, untyped changes, untyped foreign_key, untyped name, untyped touch, untyped touch_method) -> untyped def self.add_touch_callbacks: (untyped model, untyped reflection) -> untyped def self.add_default_callbacks: (untyped model, untyped reflection) -> untyped def self.add_destroy_callbacks: (untyped model, untyped reflection) -> untyped def self.define_validations: (untyped model, untyped reflection) -> untyped end end module ActiveRecord::Associations::Builder class CollectionAssociation < Association # :nodoc: # nodoc: CALLBACKS: ::Array[untyped] def self.valid_options: (untyped options) -> untyped def self.define_callbacks: (untyped model, untyped reflection) -> untyped def self.define_extensions: (untyped model, untyped name) { () -> untyped } -> untyped def self.define_callback: (untyped model, untyped callback_name, untyped name, untyped options) -> untyped # Defines the setter and getter methods for the collection_singular_ids. def self.define_readers: (untyped mixin, untyped name) -> untyped def self.define_writers: (untyped mixin, untyped name) -> untyped end end module ActiveRecord::Associations::Builder class HasAndBelongsToMany # :nodoc: # :nodoc: attr_reader lhs_model: untyped # :nodoc: # :nodoc: attr_reader association_name: untyped # :nodoc: # :nodoc: attr_reader options: untyped def initialize: (untyped association_name, untyped lhs_model, untyped options) -> untyped def through_model: () -> untyped def middle_reflection: (untyped join_model) -> untyped def middle_options: (untyped join_model) -> untyped def table_name: () -> untyped def belongs_to_options: (untyped options) -> untyped end end module ActiveRecord::Associations::Builder class HasMany < CollectionAssociation # :nodoc: # nodoc: def self.macro: () -> :has_many def self.valid_options: (untyped options) -> untyped def self.valid_dependent_options: () -> ::Array[:destroy | :delete_all | :nullify | :restrict_with_error | :restrict_with_exception] end end module ActiveRecord::Associations::Builder class HasOne < SingularAssociation # :nodoc: # nodoc: def self.macro: () -> :has_one def self.valid_options: (untyped options) -> untyped def self.valid_dependent_options: () -> ::Array[:destroy | :delete | :nullify | :restrict_with_error | :restrict_with_exception] def self.define_callbacks: (untyped model, untyped reflection) -> untyped def self.add_destroy_callbacks: (untyped model, untyped reflection) -> untyped def self.define_validations: (untyped model, untyped reflection) -> untyped def self.touch_record: (untyped o, untyped name, untyped touch) -> (nil | untyped) def self.add_touch_callbacks: (untyped model, untyped reflection) -> untyped end end module ActiveRecord::Associations::Builder class SingularAssociation < Association # :nodoc: # nodoc: def self.valid_options: (untyped options) -> untyped def self.define_accessors: (untyped model, untyped reflection) -> untyped # Defines the (build|create)_association methods for belongs_to or has_one association def self.define_constructors: (untyped mixin, untyped name) -> untyped end end module ActiveRecord module Associations class CollectionAssociation < Association # = Active Record Association Collection # # CollectionAssociation is an abstract class that provides common stuff to # ease the implementation of association proxies that represent # collections. See the class hierarchy in Association. # # CollectionAssociation: # HasManyAssociation => has_many # HasManyThroughAssociation + ThroughAssociation => has_many :through # # The CollectionAssociation class provides common methods to the collections # defined by +has_and_belongs_to_many+, +has_many+ or +has_many+ with # the +:through association+ option. # # You need to be careful with assumptions regarding the target: The proxy # does not fetch records from the database until it needs them, but new # ones created with +build+ are added to the target. So, the target may be # non-empty and still lack children waiting to be read from the database. # If you look directly to the database you cannot assume that's the entire # collection because new records may have been added to the target, etc. # # If you need to work on all current children, new and existing records, # +load_target+ and the +loaded+ flag are your friends. # nodoc: # Implements the reader method, e.g. foo.items for Foo.has_many :items def reader: () -> untyped # Implements the writer method, e.g. foo.items= for Foo.has_many :items def writer: (untyped records) -> untyped # Implements the ids reader method, e.g. foo.item_ids for Foo.has_many :items def ids_reader: () -> untyped # Implements the ids writer method, e.g. foo.item_ids= for Foo.has_many :items def ids_writer: (untyped ids) -> untyped def reset: () -> untyped def find: (*untyped args) -> untyped def build: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped # Add +records+ to this association. Since +<<+ flattens its argument list # and inserts each record, +push+ and +concat+ behave identically. def concat: (*untyped records) -> untyped # Starts a transaction in the association class's database connection. # # class Author < ActiveRecord::Base # has_many :books # end # # Author.first.books.transaction do # # same effect as calling Book.transaction # end def transaction: (*untyped args) { () -> untyped } -> untyped # Removes all records from the association without calling callbacks # on the associated records. It honors the +:dependent+ option. However # if the +:dependent+ value is +:destroy+ then in that case the +:delete_all+ # deletion strategy for the association is applied. # # You can force a particular deletion strategy by passing a parameter. # # Example: # # @author.books.delete_all(:nullify) # @author.books.delete_all(:delete_all) # # See delete for more info. def delete_all: (?untyped? dependent) -> untyped # Destroy all the records from this association. # # See destroy for more info. def destroy_all: () -> untyped # Removes +records+ from this association calling +before_remove+ and # +after_remove+ callbacks. # # This method is abstract in the sense that +delete_records+ has to be # provided by descendants. Note this method does not imply the records # are actually removed from the database, that depends precisely on # +delete_records+. They are in any case removed from the collection. def delete: (*untyped records) -> untyped # Deletes the +records+ and removes them from this association calling # +before_remove+ , +after_remove+ , +before_destroy+ and +after_destroy+ callbacks. # # Note that this method removes records from the database ignoring the # +:dependent+ option. def destroy: (*untyped records) -> untyped # Returns the size of the collection by executing a SELECT COUNT(*) # query if the collection hasn't been loaded, and calling # collection.size if it has. # # 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. # # This method is abstract in the sense that it relies on # +count_records+, which is a method descendants have to provide. def size: () -> untyped # 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.length.zero?. def empty?: () -> untyped # Replace this collection with +other_array+. This will perform a diff # and delete/add only records that have changed. def replace: (untyped other_array) -> untyped def include?: (untyped record) -> untyped def load_target: () -> untyped def add_to_target: (untyped record, ?bool skip_callbacks) { () -> untyped } -> untyped def scope: () -> untyped def null_scope?: () -> untyped def find_from_target?: () -> untyped # We have some records loaded from the database (persisted) and some that are # in-memory (memory). The same record may be represented in the persisted array # and in the memory array. # # So the task of this method is to merge them according to the following rules: # # * The final array must not have duplicates # * The order of the persisted array is to be preserved # * Any changes made to attributes on objects in the memory array are to be preserved # * Otherwise, attributes should have the value found in the database def merge_target_lists: (untyped persisted, untyped memory) -> untyped def _create_record: (untyped attributes, ?bool raise) { () -> untyped } -> untyped # Do the relevant stuff to insert the given record into the association collection. def insert_record: (untyped record, ?bool validate, ?bool raise) { () -> untyped } -> untyped def delete_or_destroy: (untyped records, untyped method) -> (nil | untyped) def remove_records: (untyped existing_records, untyped records, untyped method) -> (nil | untyped) # Delete the given records from the association, # using one of the methods +:destroy+, +:delete_all+ # or +:nullify+ (or +nil+, in which case a default is used). def delete_records: (untyped records, untyped method) -> untyped def replace_records: (untyped new_target, untyped original_target) -> untyped def replace_common_records_in_memory: (untyped new_target, untyped original_target) -> untyped def concat_records: (untyped records, ?bool raise) -> untyped def replace_on_target: (untyped record, untyped index, untyped skip_callbacks) { (untyped) -> untyped } -> untyped def callback: (untyped method, untyped record) -> untyped def callbacks_for: (untyped callback_name) -> untyped def include_in_memory?: (untyped record) -> untyped # If the :inverse_of option has been # specified, then #find scans the entire collection. def find_by_scan: (*untyped args) -> untyped end end end module ActiveRecord module Associations # 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. class CollectionProxy < Relation def initialize: (untyped klass, untyped association) -> untyped def target: () -> untyped def load_target: () -> untyped # Returns +true+ if the association has been loaded, otherwise +false+. # # person.pets.loaded? # => false # person.pets # person.pets.loaded? # => true def loaded?: () -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.find(1) # => # # person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with 'id'=4 # # person.pets.find(2) { |pet| pet.name.downcase! } # # => # # # person.pets.find(2, 3) # # => [ # # #, # # # # # ] def find: (*untyped args) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.last # => # # # person.pets.last(2) # # => [ # # #, # # # # # ] # # another_person_without.pets # => [] # another_person_without.pets.last # => nil # another_person_without.pets.last(3) # => [] def last: (?untyped? limit) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.take # => # # # person.pets.take(2) # # => [ # # #, # # # # # ] # # another_person_without.pets # => [] # another_person_without.pets.take # => nil # another_person_without.pets.take(2) # => [] def take: (?untyped? limit) -> untyped # 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 # # => # # # person.pets.build(name: 'Fancy-Fancy') # # => # # # person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}]) # # => [ # # #, # # #, # # # # # ] # # person.pets.size # => 5 # size of the collection # person.pets.count # => 0 # count from database def build: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped # 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') # # => # # # person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}]) # # => [ # # #, # # # # # ] # # person.pets.size # => 3 # person.pets.count # => 3 # # person.pets.find(1, 2, 3) # # => [ # # #, # # #, # # # # # ] def create: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped # 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 def create!: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped # 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 # # => [#] # # other_pets = [Pet.new(name: 'Puff', group: 'celebrities'] # # person.pets.replace(other_pets) # # person.pets # # => [#] # # 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 def replace: (untyped other_array) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete_all # # => [ # # #, # # #, # # # # # ] # # person.pets.size # => 0 # person.pets # => [] # # Pet.find(1, 2, 3) # # => [ # # #, # # #, # # # # # ] # # 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 # # => [ # # #, # # #, # # # # # ] # # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete_all # # Pet.find(1, 2, 3) # # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3) def delete_all: (?untyped? dependent) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.destroy_all # # person.pets.size # => 0 # person.pets # => [] # # Pet.find(1) # => Couldn't find Pet with id=1 def destroy_all: () -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete(Pet.find(1)) # # => [#] # # person.pets.size # => 2 # person.pets # # => [ # # #, # # # # # ] # # Pet.find(1) # # => # # # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete(Pet.find(1), Pet.find(3)) # # => [ # # #, # # # # # ] # # person.pets.size # => 1 # person.pets # # => [#] # # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete(Pet.find(1)) # # => [#] # # person.pets.size # => 2 # person.pets # # => [ # # #, # # # # # ] # # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.delete("1") # # => [#] # # person.pets.delete(2, 3) # # => [ # # #, # # # # # ] def delete: (*untyped records) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.destroy(Pet.find(1)) # # => [#] # # person.pets.size # => 2 # person.pets # # => [ # # #, # # # # # ] # # person.pets.destroy(Pet.find(2), Pet.find(3)) # # => [ # # #, # # # # # ] # # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.destroy("4") # # => # # # person.pets.size # => 2 # person.pets # # => [ # # #, # # # # # ] # # person.pets.destroy(5, 6) # # => [ # # #, # # # # # ] # # person.pets.size # => 0 # person.pets # => [] # # Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6) def destroy: (*untyped records) -> untyped # - def calculate: (untyped operation, untyped column_name) -> untyped def pluck: (*untyped column_names) -> untyped # 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 # # => [ # # #, # # #, # # # # # ] # # person.pets.size # => 3 # # Because the collection is already loaded, this will behave like # # collection.size and no SQL count query is executed. def size: () -> untyped # 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.length.zero?. # # 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 def empty?: () -> untyped # Returns +true+ if the given +record+ is present in the collection. # # class Person < ActiveRecord::Base # has_many :pets # end # # person.pets # => [#] # # person.pets.include?(Pet.find(20)) # => true # person.pets.include?(Pet.find(21)) # => false def include?: (untyped record) -> untyped def proxy_association: () -> untyped # Returns a Relation object for the records in this association def scope: () -> untyped # 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 # # => [ # # #, # # # # # ] # # other = person.pets.to_ary # # person.pets == other # # => true # # other = [Pet.new(id: 1), Pet.new(id: 2)] # # person.pets == other # # => false def ==: (untyped other) -> untyped def records: () -> untyped # 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 # # => [ # # #, # # #, # # # # # ] def <<: (*untyped records) -> untyped def `prepend`: (*untyped args) -> untyped # 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. def clear: () -> untyped # Reloads the collection from the database. Returns +self+. # # class Person < ActiveRecord::Base # has_many :pets # end # # person.pets # fetches pets from the database # # => [#] # # person.pets # uses the pets cache # # => [#] # # person.pets.reload # fetches pets from the database # # => [#] def reload: () -> untyped # Unloads the association. Returns +self+. # # class Person < ActiveRecord::Base # has_many :pets # end # # person.pets # fetches pets from the database # # => [#] # # person.pets # uses the pets cache # # => [#] # # person.pets.reset # clears the pets cache # # person.pets # fetches pets from the database # # => [#] def reset: () -> untyped def reset_scope: () -> untyped def find_nth_with_limit: (untyped index, untyped limit) -> untyped def find_nth_from_last: (untyped index) -> untyped def null_scope?: () -> untyped def find_from_target?: () -> untyped def exec_queries: () -> untyped end end end module ActiveRecord::Associations module ForeignAssociation # :nodoc: def foreign_key_present?: () -> untyped def nullified_owner_attributes: () -> untyped end end module ActiveRecord module Associations class HasManyAssociation < CollectionAssociation # = Active Record Has Many Association # This is the proxy that handles a has many association. # # If the association has a :through option further specialization # is provided by its child HasManyThroughAssociation. # nodoc: include ForeignAssociation def handle_dependency: () -> untyped def insert_record: (untyped record, ?bool validate, ?bool raise) -> untyped # Returns the number of records in this collection. # # If the association has a counter cache it gets that value. Otherwise # it will attempt to do a count via SQL, bounded to :limit if # there's one. Some configuration options like :group make it impossible # to do an SQL count, in those cases the array count will be used. # # That does not depend on whether the collection has already been loaded # or not. The +size+ method is the one that takes the loaded flag into # account and delegates to +count_records+ if needed. # # If the collection is empty the target is set to an empty array and # the loaded flag is set to true as well. def count_records: () -> untyped def update_counter: (untyped difference, ?untyped reflection) -> untyped def update_counter_in_memory: (untyped difference, ?untyped reflection) -> untyped def delete_count: (untyped method, untyped scope) -> untyped def delete_or_nullify_all_records: (untyped method) -> untyped # Deletes the records according to the :dependent option. def delete_records: (untyped records, untyped method) -> untyped def concat_records: (untyped records) -> untyped def _create_record: (untyped attributes) -> untyped def update_counter_if_success: (untyped saved_successfully, untyped difference) -> untyped def difference: (untyped a, untyped b) -> untyped def intersection: (untyped a, untyped b) -> untyped end end end module ActiveRecord module Associations class HasManyThroughAssociation < HasManyAssociation # = Active Record Has Many Through Association # nodoc: include ThroughAssociation def initialize: (untyped owner, untyped reflection) -> untyped def concat: (*untyped records) -> untyped def insert_record: (untyped record, ?bool validate, ?bool raise) -> (nil | untyped) def concat_records: (untyped records) -> untyped # The through record (built with build_record) is temporarily cached # so that it may be reused if insert_record is subsequently called. # # However, after insert_record has been called, the cache is cleared in # order to allow multiple instances of the same record in an association. def build_through_record: (untyped record) -> untyped def through_scope_attributes: () -> untyped def save_through_record: (untyped record) -> untyped def build_record: (untyped attributes) -> untyped def remove_records: (untyped existing_records, untyped records, untyped method) -> untyped def target_reflection_has_associated_record?: () -> untyped def update_through_counter?: (untyped method) -> untyped def delete_or_nullify_all_records: (untyped method) -> untyped def delete_records: (untyped records, untyped method) -> untyped def difference: (untyped a, untyped b) -> untyped def intersection: (untyped a, untyped b) -> untyped def mark_occurrence: (untyped distribution, untyped record) -> untyped def distribution: (untyped array) -> untyped def through_records_for: (untyped record) -> untyped def delete_through_records: (untyped records) -> untyped def find_target: () -> (::Array[untyped] | untyped) # NOTE - not sure that we can actually cope with inverses here def invertible_for?: (untyped record) -> ::FalseClass end end end module ActiveRecord module Associations class HasOneAssociation < SingularAssociation # = Active Record Has One Association # nodoc: include ForeignAssociation def handle_dependency: () -> untyped def delete: (?untyped method) -> untyped def replace: (untyped record, ?bool save) -> untyped # The reason that the save param for replace is false, if for create (not just build), # is because the setting of the foreign keys is actually handled by the scoping when # the record is instantiated, and so they are set straight away and do not need to be # updated within replace. def set_new_record: (untyped record) -> untyped def remove_target!: (untyped method) -> untyped def nullify_owner_attributes: (untyped record) -> untyped def transaction_if: (untyped value) { () -> untyped } -> untyped def _create_record: (untyped attributes, ?bool raise_error) { () -> untyped } -> untyped end end end module ActiveRecord module Associations class HasOneThroughAssociation < HasOneAssociation # = Active Record Has One Through Association # nodoc: include ThroughAssociation def replace: (untyped record, ?bool save) -> untyped def create_through_record: (untyped record, untyped save) -> untyped end end end module ActiveRecord module Associations class JoinDependency class JoinAssociation < JoinPart # :nodoc: # :nodoc: attr_reader reflection: untyped # :nodoc: # :nodoc: attr_reader tables: untyped attr_accessor table: untyped def initialize: (untyped reflection, untyped children) -> untyped def match?: (untyped other) -> (::TrueClass | untyped) def join_constraints: (untyped foreign_table, untyped foreign_klass, untyped join_type, untyped alias_tracker) -> untyped def tables=: (untyped tables) -> untyped def readonly?: () -> untyped def append_constraints: (untyped join, untyped constraints) -> untyped end end end end module ActiveRecord module Associations class JoinDependency class JoinBase < JoinPart # :nodoc: # :nodoc: attr_reader table: untyped def initialize: (untyped base_klass, untyped table, untyped children) -> untyped def match?: (untyped other) -> (::TrueClass | untyped) end end end end module ActiveRecord module Associations class JoinDependency class JoinPart # :nodoc: # A JoinPart represents a part of a JoinDependency. It is inherited # by JoinBase and JoinAssociation. A JoinBase represents the Active Record which # everything else is being joined onto. A JoinAssociation represents an association which # is joining to the base. A JoinAssociation may result in more than one actual join # operations (for example a has_and_belongs_to_many JoinAssociation would result in # two; one for the join table and one for the target table). # :nodoc: include Enumerable[untyped, untyped] # The Active Record class which this join part is associated 'about'; for a JoinBase # this is the actual base model, for a JoinAssociation this is the target model of the # association. attr_reader base_klass: untyped # The Active Record class which this join part is associated 'about'; for a JoinBase # this is the actual base model, for a JoinAssociation this is the target model of the # association. attr_reader children: untyped def initialize: (untyped base_klass, untyped children) -> untyped def match?: (untyped other) -> untyped def each: () { (untyped) -> untyped } -> untyped def each_children: () { (untyped, untyped) -> untyped } -> untyped # An Arel::Table for the active_record def table: () -> untyped def extract_record: (untyped row, untyped column_names_with_alias) -> untyped def instantiate: (untyped row, untyped aliases) { () -> untyped } -> untyped end end end end module ActiveRecord module Associations class JoinDependency class Aliases # :nodoc: def initialize: (untyped tables) -> untyped def columns: () -> untyped def column_aliases: (untyped node) -> untyped def column_alias: (untyped node, untyped column) -> untyped class Table < ::Struct[untyped] attr_accessor node(): untyped attr_accessor columns(): untyped # :nodoc: def column_aliases: () -> untyped end class Column < ::Struct[untyped] attr_accessor name(): untyped attr_accessor alias(): untyped end end def self.make_tree: (untyped associations) -> untyped def self.walk_tree: (untyped associations, untyped hash) -> untyped def initialize: (untyped base, untyped table, untyped associations, untyped join_type) -> untyped def base_klass: () -> untyped def reflections: () -> untyped def join_constraints: (untyped joins_to_add, untyped alias_tracker) -> untyped def instantiate: (untyped result_set) { () -> untyped } -> untyped def apply_column_aliases: (untyped relation) -> untyped attr_reader join_root: untyped attr_reader join_type: untyped attr_reader alias_tracker: untyped def explicit_selections: (untyped root_column_aliases, untyped result_set) -> untyped def aliases: () -> untyped def construct_tables!: (untyped join_root) -> untyped def make_join_constraints: (untyped join_root, untyped join_type) -> untyped def make_constraints: (untyped parent, untyped child, untyped join_type) -> untyped def table_aliases_for: (untyped parent, untyped node) -> untyped def table_alias_for: (untyped reflection, untyped parent, untyped join) -> untyped def walk: (untyped left, untyped right, untyped join_type) -> untyped def find_reflection: (untyped klass, untyped name) -> untyped def build: (untyped associations, untyped base_klass) -> untyped def construct: (untyped ar_parent, untyped parent, untyped row, untyped seen, untyped model_cache) -> (nil | untyped) def construct_model: (untyped record, untyped node, untyped row, untyped model_cache, untyped id) -> untyped end end end module ActiveRecord module Associations class Preloader class Association # nodoc: def initialize: (untyped klass, untyped owners, untyped reflection, untyped preload_scope) -> untyped def run: () -> untyped def records_by_owner: () -> untyped def preloaded_records: () -> untyped attr_reader owners: untyped attr_reader reflection: untyped attr_reader preload_scope: untyped attr_reader model: untyped attr_reader klass: untyped # The name of the key on the associated records def association_key_name: () -> untyped # The name of the key on the model which declares the association def owner_key_name: () -> untyped def associate_records_to_owner: (untyped owner, untyped records) -> untyped def owner_keys: () -> untyped def owners_by_key: () -> untyped def key_conversion_required?: () -> untyped def convert_key: (untyped key) -> untyped def association_key_type: () -> untyped def owner_key_type: () -> untyped def records_for: (untyped ids) -> untyped def scope: () -> untyped def reflection_scope: () -> untyped def build_scope: () -> untyped end end end end module ActiveRecord module Associations class Preloader # Implements the details of eager loading of Active Record associations. # # Suppose that you have the following two Active Record models: # # class Author < ActiveRecord::Base # # columns: name, age # has_many :books # end # # class Book < ActiveRecord::Base # # columns: title, sales, author_id # end # # When you load an author with all associated books Active Record will make # multiple queries like this: # # Author.includes(:books).where(name: ['bell hooks', 'Homer']).to_a # # => SELECT `authors`.* FROM `authors` WHERE `name` IN ('bell hooks', 'Homer') # => SELECT `books`.* FROM `books` WHERE `author_id` IN (2, 5) # # Active Record saves the ids of the records from the first query to use in # the second. Depending on the number of associations involved there can be # arbitrarily many SQL queries made. # # However, if there is a WHERE clause that spans across tables Active # Record will fall back to a slightly more resource-intensive single query: # # Author.includes(:books).where(books: {title: 'Illiad'}).to_a # => SELECT `authors`.`id` AS t0_r0, `authors`.`name` AS t0_r1, `authors`.`age` AS t0_r2, # `books`.`id` AS t1_r0, `books`.`title` AS t1_r1, `books`.`sales` AS t1_r2 # FROM `authors` # LEFT OUTER JOIN `books` ON `authors`.`id` = `books`.`author_id` # WHERE `books`.`title` = 'Illiad' # # This could result in many rows that contain redundant data and it performs poorly at scale # and is therefore only used when necessary. # # nodoc: extend ActiveSupport::Autoload # Eager loads the named associations for the given Active Record record(s). # # In this description, 'association name' shall refer to the name passed # to an association creation method. For example, a model that specifies # belongs_to :author, has_many :buyers has association # names +:author+ and +:buyers+. # # == Parameters # +records+ is an array of ActiveRecord::Base. This array needs not be flat, # i.e. +records+ itself may also contain arrays of records. In any case, # +preload_associations+ will preload the all associations records by # flattening +records+. # # +associations+ specifies one or more associations that you want to # preload. It may be: # - a Symbol or a String which specifies a single association name. For # example, specifying +:books+ allows this method to preload all books # for an Author. # - an Array which specifies multiple association names. This array # is processed recursively. For example, specifying [:avatar, :books] # allows this method to preload an author's avatar as well as all of his # books. # - a Hash which specifies multiple association names, as well as # association names for the to-be-preloaded association objects. For # example, specifying { author: :avatar } will preload a # book's author, as well as that author's avatar. # # +:associations+ has the same format as the +:include+ option for # ActiveRecord::Base.find. So +associations+ could look like this: # # :books # [ :books, :author ] # { author: :avatar } # [ :books, { author: :avatar } ] def preload: (untyped records, untyped associations, ?untyped? preload_scope) -> untyped # Loads all the given data into +records+ for the +association+. def preloaders_on: (untyped association, untyped records, untyped scope, ?bool polymorphic_parent) -> untyped def preloaders_for_hash: (untyped association, untyped records, untyped scope, untyped polymorphic_parent) -> untyped # Loads all the given data into +records+ for a singular +association+. # # Functions by instantiating a preloader class such as Preloader::Association and # call the +run+ method for each passed in class in the +records+ argument. # # Not all records have the same class, so group then preload group on the reflection # itself so that if various subclass share the same association then we do not split # them unnecessarily # # Additionally, polymorphic belongs_to associations can have multiple associated # classes, depending on the polymorphic_type field. So we group by the classes as # well. def preloaders_for_one: (untyped association, untyped records, untyped scope, untyped polymorphic_parent) -> untyped def preloaders_for_reflection: (untyped reflection, untyped records, untyped scope) -> untyped def grouped_records: (untyped association, untyped records, untyped polymorphic_parent) -> untyped class AlreadyLoaded # :nodoc: def initialize: (untyped klass, untyped owners, untyped reflection, untyped preload_scope) -> untyped def run: () -> untyped def preloaded_records: () -> untyped def records_by_owner: () -> untyped attr_reader owners: untyped attr_reader reflection: untyped end # Returns a class containing the logic needed to load preload the data # and attach it to a relation. The class returned implements a `run` method # that accepts a preloader. def preloader_for: (untyped reflection, untyped owners) -> untyped end end end module ActiveRecord module Associations class Preloader class ThroughAssociation < Association # :nodoc: PRELOADER: untyped def initialize: () -> untyped def preloaded_records: () -> untyped def records_by_owner: () -> untyped def source_preloaders: () -> untyped def middle_records: () -> untyped def through_preloaders: () -> untyped def through_reflection: () -> untyped def source_reflection: () -> untyped def preload_index: () -> untyped def through_scope: () -> untyped end end end end module ActiveRecord class AssociationNotFoundError < ConfigurationError # nodoc: def initialize: (?untyped? record, ?untyped? association_name) -> untyped end class InverseOfAssociationNotFoundError < ActiveRecordError # nodoc: def initialize: (?untyped? reflection, ?untyped? associated_class) -> untyped end class HasManyThroughAssociationNotFoundError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection) -> untyped end class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection, ?untyped? source_reflection) -> untyped end class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection) -> untyped end class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection, ?untyped? source_reflection) -> untyped end class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection, ?untyped? through_reflection) -> untyped end class HasOneAssociationPolymorphicThroughError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection) -> untyped end class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # nodoc: def initialize: (?untyped? reflection) -> untyped end class HasManyThroughOrderError < ActiveRecordError # nodoc: def initialize: (?untyped? owner_class_name, ?untyped? reflection, ?untyped? through_reflection) -> untyped end class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # nodoc: def initialize: (?untyped? owner, ?untyped? reflection) -> untyped end class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc: def initialize: (untyped klass, untyped macro, untyped association_name, untyped options, untyped possible_sources) -> untyped end class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection end class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection end class ThroughNestedAssociationsAreReadonly < ActiveRecordError # nodoc: def initialize: (?untyped? owner, ?untyped? reflection) -> untyped end class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly end class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly end # 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}[rdoc-ref:QueryMethods#preload]. class EagerLoadPolymorphicError < ActiveRecordError def initialize: (?untyped? reflection) -> untyped end class DeleteRestrictionError < ActiveRecordError # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations # (has_many, has_one) when there is at least 1 child associated instance. # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project # nodoc: def initialize: (?untyped? name) -> untyped end module Associations # See ActiveRecord::Associations::ClassMethods for documentation. # :nodoc: extend ActiveSupport::Autoload extend ActiveSupport::Concern module Builder end def self.eager_load!: () -> untyped def association: (untyped name) -> untyped def association_cached?: (untyped name) -> untyped def initialize_dup: () -> untyped def reload: () -> untyped # Clears out the association cache. def clear_association_cache: () -> untyped def init_internals: () -> untyped # Returns the specified association instance if it exists, +nil+ otherwise. def association_instance_get: (untyped name) -> untyped # Set the specified association instance. def association_instance_set: (untyped name, untyped association) -> untyped # \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}[rdoc-ref:ActiveRecord::Core] 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 # # === 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, eager loading and preloading of these associations is not possible. # These operations happen before instance creation and the scope will be called with a +nil+ argument. # # == 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 Project # has_and_belongs_to_many :developers, after_add: :evaluate_velocity # # def evaluate_velocity(developer) # ... # end # end # # It's possible to stack callbacks by passing them as an array. Example: # # class Project # has_and_belongs_to_many :developers, # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}] # 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. # # == 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. # # Extra options on the associations, as defined in the # AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS # constant, or a custom scope, will also prevent the association's inverse # from being found automatically. # # 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. module ClassMethods # 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. # # * :destroy causes all the associated objects to also be destroyed. # * :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.) # [: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. # # 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 def has_many: (untyped name, ?untyped? scope, **untyped options) { () -> untyped } -> untyped # 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: # # * :destroy causes the associated object to also be destroyed # * :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 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. # [: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. # [: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. # # 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 :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable # has_one :credit_card, required: true def has_one: (untyped name, ?untyped? scope, **untyped options) -> untyped # 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. # # === 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 # 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. # 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/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/on attribute. # Please note that with touching no validation is performed and only the +after_touch+, # +after_commit+ and +after_rollback+ callbacks are 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. # # 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 } def belongs_to: (untyped name, ?untyped? scope, **untyped options) -> untyped # 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[5.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. # # 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 } def has_and_belongs_to_many: (untyped name, ?untyped? scope, **untyped options) { () -> untyped } -> untyped end end end module ActiveRecord module Associations class SingularAssociation < Association # nodoc: # Implements the reader method, e.g. foo.bar for Foo.has_one :bar def reader: () -> untyped # Implements the writer method, e.g. foo.bar= for Foo.belongs_to :bar def writer: (untyped record) -> untyped def build: (?::Hash[untyped, untyped] attributes) { () -> untyped } -> untyped # Implements the reload reader method, e.g. foo.reload_bar for # Foo.has_one :bar def force_reload_reader: () -> untyped def scope_for_create: () -> untyped def find_target: () -> untyped def replace: (untyped record) -> untyped def set_new_record: (untyped record) -> untyped def _create_record: (untyped attributes, ?bool raise_error) { () -> untyped } -> untyped end end end module ActiveRecord module Associations module ThroughAssociation def through_reflection: () -> untyped def through_association: () -> untyped # We merge in these scopes for two reasons: # # 1. To get the default_scope conditions for any of the other reflections in the chain # 2. To get the type conditions for any STI models in the chain def target_scope: () -> untyped # Construct attributes for :through pointing to owner and associate. This is used by the # methods which create and delete records on the association. # # We only support indirectly modifying through associations which have a belongs_to source. # This is the "has_many :tags, through: :taggings" situation, where the join model # typically has a belongs_to on both side. In other words, associations which could also # be represented as has_and_belongs_to_many associations. # # We do not support creating/deleting records on the association where the source has # some other type, because this opens up a whole can of worms, and in basically any # situation it is more natural for the user to just create or modify their join records # directly as required. def construct_join_attributes: (*untyped records) -> untyped # Note: this does not capture all cases, for example it would be crazy to try to # properly support stale-checking for nested associations. def stale_state: () -> untyped def foreign_key_present?: () -> untyped def ensure_mutable: () -> untyped def ensure_not_nested: () -> untyped def build_record: (untyped attributes) -> untyped end end end module ActiveRecord module AttributeAssignment include ActiveModel::AttributeAssignment def _assign_attributes: (untyped attributes) -> untyped # Assign any deferred nested attributes after the base attributes have been set. def assign_nested_parameter_attributes: (untyped pairs) -> untyped # Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done # by calling new on the column type or aggregation type (through composed_of) object with these parameters. # So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate # written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the # parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and # f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+. def assign_multiparameter_attributes: (untyped pairs) -> untyped def execute_callstack_for_multiparameter_attributes: (untyped callstack) -> untyped def extract_callstack_for_multiparameter_attributes: (untyped pairs) -> untyped def type_cast_attribute_value: (untyped multiparameter_name, untyped value) -> untyped def find_parameter_position: (untyped multiparameter_name) -> untyped end end module ActiveRecord module AttributeDecorators # :nodoc: extend ActiveSupport::Concern module ClassMethods # :nodoc: # This method is an internal API used to create class macros such as # +serialize+, and features like time zone aware attributes. # # Used to wrap the type of an attribute in a new type. # When the schema for a model is loaded, attributes with the same name as # +column_name+ will have their type yielded to the given block. The # return value of that block will be used instead. # # Subsequent calls where +column_name+ and +decorator_name+ are the same # will override the previous decorator, not decorate twice. This can be # used to create idempotent class macros like +serialize+ def decorate_attribute_type: (untyped column_name, untyped decorator_name) { () -> untyped } -> untyped # This method is an internal API used to create higher level features like # time zone aware attributes. # # When the schema for a model is loaded, +matcher+ will be called for each # attribute with its name and type. If the matcher returns a truthy value, # the type will then be yielded to the given block, and the return value # of that block will replace the type. # # Subsequent calls to this method with the same value for +decorator_name+ # will replace the previous decorator, not decorate twice. This can be # used to ensure that class macros are idempotent. def decorate_matching_attribute_types: (untyped matcher, untyped decorator_name) { () -> untyped } -> untyped def load_schema!: () -> untyped end class TypeDecorator def initialize: (?::Hash[untyped, untyped] decorations) -> untyped def merge: (*untyped args) -> TypeDecorator def apply: (untyped name, untyped `type`) -> untyped def decorators_for: (untyped name, untyped `type`) -> untyped def matching: (untyped name, untyped `type`) -> untyped end end end module ActiveRecord module AttributeMethods extend ::ActiveRecord::AttributeMethods::Serialization::ClassMethods extend ::ActiveRecord::AttributeMethods::TimeZoneConversion::ClassMethods extend ::ActiveRecord::AttributeMethods::PrimaryKey::ClassMethods extend ::ActiveRecord::AttributeMethods::Write::ClassMethods extend ::ActiveRecord::AttributeMethods::Read::ClassMethods extend ::ActiveModel::AttributeMethods::ClassMethods # = 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" module BeforeTypeCast extend ActiveSupport::Concern # 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" def read_attribute_before_type_cast: (untyped attr_name) -> untyped # 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} def attributes_before_type_cast: () -> untyped # Dispatch target for *_before_type_cast attribute methods. def attribute_before_type_cast: (untyped attribute_name) -> untyped def attribute_came_from_user?: (untyped attribute_name) -> untyped end end end module ActiveRecord module AttributeMethods module Dirty extend ActiveSupport::Concern include ActiveModel::Dirty # reload the record and clears changed attributes. def reload: () -> untyped # 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 def saved_change_to_attribute?: (untyped attr_name, **untyped options) -> untyped # 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"). def saved_change_to_attribute: (untyped attr_name) -> untyped # 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"). def attribute_before_last_save: (untyped attr_name) -> untyped # Did the last call to +save+ have any changes to change? def saved_changes?: () -> untyped # Returns a hash containing all the changes that were just saved. def saved_changes: () -> untyped # 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 def will_save_change_to_attribute?: (untyped attr_name, **untyped options) -> untyped # 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. def attribute_change_to_be_saved: (untyped attr_name) -> untyped # 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"). def attribute_in_database: (untyped attr_name) -> untyped # Will the next call to +save+ have any changes to persist? def has_changes_to_save?: () -> untyped # Returns a hash containing all the changes that will be persisted during # the next save. def changes_to_save: () -> untyped # Returns an array of the names of any attributes that will change when # the record is next saved. def changed_attribute_names_to_save: () -> untyped # 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). def attributes_in_database: () -> untyped def mutations_from_database: () -> untyped def mutations_before_last_save: () -> untyped def write_attribute_without_type_cast: (untyped attr_name, untyped value) -> untyped def _touch_row: (untyped attribute_names, untyped time) -> untyped def _update_record: (?untyped attribute_names) -> untyped def _create_record: (?untyped attribute_names) -> untyped def attribute_names_for_partial_writes: () -> untyped end end end module ActiveRecord module AttributeMethods module PrimaryKey extend ActiveSupport::Concern # Returns this record's primary key value wrapped in an array if one is # available. def to_key: () -> untyped # Returns the primary key column's value. def id: () -> untyped # Sets the primary key column's value. def id=: (untyped value) -> untyped # Queries the primary key column's value. def id?: () -> untyped # Returns the primary key column's value before type cast. def id_before_type_cast: () -> untyped # Returns the primary key column's previous value. def id_was: () -> untyped # Returns the primary key column's value from the database. def id_in_database: () -> untyped def attribute_method?: (untyped attr_name) -> untyped module ClassMethods ID_ATTRIBUTE_METHODS: untyped def instance_method_already_implemented?: (untyped method_name) -> untyped def dangerous_attribute_method?: (untyped method_name) -> untyped # Defines the primary key field -- can be overridden in subclasses. # Overwriting will negate any effect of the +primary_key_prefix_type+ # setting, though. def primary_key: () -> untyped # Returns a quoted version of the primary key name, used to construct # SQL statements. def quoted_primary_key: () -> untyped def reset_primary_key: () -> untyped def get_primary_key: (untyped base_name) -> untyped # 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" def primary_key=: (untyped value) -> untyped def suppress_composite_primary_key: (untyped pk) -> untyped end end end end module ActiveRecord module AttributeMethods module Query extend ActiveSupport::Concern def query_attribute: (untyped attr_name) -> (::FalseClass | untyped) # Dispatch target for *? attribute methods. def attribute?: (untyped attribute_name) -> untyped end end end module ActiveRecord # = Active Record Attribute Methods module AttributeMethods extend ActiveSupport::Concern include ActiveModel::AttributeMethods include Read include Write include BeforeTypeCast include Query include PrimaryKey include TimeZoneConversion include Dirty include Serialization RESTRICTED_CLASS_METHODS: ::Array[untyped] class GeneratedAttributeMethods < Module # nodoc: include Mutex_m end module ClassMethods def inherited: (untyped child_class) -> untyped def initialize_generated_modules: () -> untyped def define_attribute_methods: () -> (::FalseClass | untyped) def undefine_attribute_methods: () -> untyped # 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 def instance_method_already_implemented?: (untyped method_name) -> untyped def dangerous_attribute_method?: (untyped name) -> untyped def method_defined_within?: (untyped name, untyped klass, ?untyped superklass) -> untyped # 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.) def dangerous_class_method?: (untyped method_name) -> untyped def class_method_defined_within?: (untyped name, untyped klass, ?untyped superklass) -> untyped # 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 def attribute_method?: (untyped attribute) -> untyped # 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"] def attribute_names: () -> untyped # Returns true if the given attribute exists, otherwise false. # # class Person < ActiveRecord::Base # end # # Person.has_attribute?('name') # => true # Person.has_attribute?(:age) # => true # Person.has_attribute?(:nothing) # => false def has_attribute?: (untyped attr_name) -> untyped # Returns the column object for the named attribute. # Returns a +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 # # => # # # person.column_for_attribute(:nothing) # # => #, ...> def column_for_attribute: (untyped name) -> untyped end # 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 def respond_to?: (untyped name, ?bool include_private) -> (::FalseClass | untyped | ::TrueClass) # Returns +true+ if the given attribute is in the attributes hash, otherwise +false+. # # class Person < ActiveRecord::Base # end # # person = Person.new # person.has_attribute?(:name) # => true # person.has_attribute?('age') # => true # person.has_attribute?(:nothing) # => false def has_attribute?: (untyped attr_name) -> untyped # 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"] def attribute_names: () -> untyped # 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} def attributes: () -> untyped # Returns an #inspect-like string for the value of the # attribute +attr_name+. String attributes are truncated up to 50 # characters, Date and Time attributes are returned in the # :db format. 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\"" # # person.attribute_for_inspect(:tag_ids) # # => "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]" def attribute_for_inspect: (untyped attr_name) -> untyped # 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 def attribute_present?: (untyped attribute) -> untyped # 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 def []: (untyped attr_name) -> untyped # Updates the attribute identified by attr_name with the specified +value+. # (Alias for the protected #write_attribute method). # # class Person < ActiveRecord::Base # end # # person = Person.new # person[:age] = '22' # person[:age] # => 22 # person[:age].class # => Integer def []=: (untyped attr_name, untyped value) -> untyped # 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 def accessed_fields: () -> untyped def attribute_method?: (untyped attr_name) -> untyped def attributes_with_values: (untyped attribute_names) -> untyped # Filters the primary keys and readonly attributes from the attribute names. def attributes_for_update: (untyped attribute_names) -> untyped # Filters out the primary keys, from the attribute names, when the primary # key is to be generated (e.g. the id attribute has no value). def attributes_for_create: (untyped attribute_names) -> untyped def format_for_inspect: (untyped value) -> untyped def readonly_attribute?: (untyped name) -> untyped def pk_attribute?: (untyped name) -> untyped end end module ActiveRecord module AttributeMethods module Read extend ActiveSupport::Concern module ClassMethods def define_method_attribute: (untyped name) -> untyped end # 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)). def read_attribute: (untyped attr_name) { () -> untyped } -> untyped def _read_attribute: (untyped attr_name) { () -> untyped } -> untyped end end end module ActiveRecord module AttributeMethods module Serialization extend ActiveSupport::Concern class ColumnNotSerializableError < StandardError def initialize: (untyped name, untyped `type`) -> untyped end module ClassMethods # If you have an attribute that needs to be saved to the database as an # object, and retrieved as the same object, then specify the name of that # attribute using this method and it will be handled automatically. The # serialization is done through YAML. If +class_name+ is specified, the # serialized object must be of that class on assignment and retrieval. # Otherwise SerializationTypeMismatch will be raised. # # Empty objects as {}, in the case of +Hash+, or [], in the case of # +Array+, will always be persisted as null. # # 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 field name that should be serialized. # * +class_name_or_coder+ - Optional, a coder object, which responds to +.load+ and +.dump+ # or a class name that the object type should be equal to. # # ==== Example # # # Serialize a preferences attribute. # class User < ActiveRecord::Base # serialize :preferences # end # # # Serialize preferences using JSON as coder. # class User < ActiveRecord::Base # serialize :preferences, JSON # end # # # Serialize preferences as Hash using YAML coder. # class User < ActiveRecord::Base # serialize :preferences, Hash # end def serialize: (untyped attr_name, ?untyped class_name_or_coder) -> untyped def type_incompatible_with_serialize?: (untyped `type`, untyped class_name) -> untyped end end end end module ActiveRecord module AttributeMethods module TimeZoneConversion # Note: It inherits unnamed class, but omitted class TimeZoneConverter # :nodoc: def deserialize: (untyped value) -> untyped def cast: (untyped value) -> (nil | untyped) def convert_time_to_time_zone: (untyped value) -> (nil | untyped) def set_time_zone_without_conversion: (untyped value) -> untyped def map_avoiding_infinite_recursion: (untyped value) { (untyped) -> untyped } -> untyped end extend ActiveSupport::Concern module ClassMethods def inherited: (untyped subclass) -> untyped def create_time_zone_conversion_attribute?: (untyped name, untyped cast_type) -> untyped end end end end module ActiveRecord module AttributeMethods module Write extend ActiveSupport::Concern module ClassMethods def define_method_attribute=: (untyped name) -> untyped end # Updates the attribute identified by attr_name with the # specified +value+. Empty strings for Integer and Float columns are # turned into +nil+. def write_attribute: (untyped attr_name, untyped value) -> untyped def _write_attribute: (untyped attr_name, untyped value) -> untyped def write_attribute_without_type_cast: (untyped attr_name, untyped value) -> untyped # Dispatch target for *= attribute methods. def attribute=: (untyped attribute_name, untyped value) -> untyped end end end module ActiveRecord # See ActiveRecord::Attributes::ClassMethods for documentation module Attributes extend ActiveSupport::Concern module ClassMethods # 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}[rdoc-ref:QueryMethods#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}[rdoc-ref:QueryMethods#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 < 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. def attribute: (untyped name, ?untyped cast_type, **untyped options) -> untyped # 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+. def define_attribute: (untyped name, untyped cast_type, ?user_provided_default: bool user_provided_default, ?default: untyped default) -> untyped def load_schema!: () -> untyped NO_DEFAULT_PROVIDED: untyped def define_default_attribute: (untyped name, untyped value, untyped `type`, from_user: untyped from_user) -> untyped end end end module ActiveRecord # = 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 (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') # post.comments.create(body: 'hello world') # post.save # => saves both post and 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') # post.comments.create(body: 'hello world') # post.comments[0].body = 'hi everyone' # post.comments.build(body: "good morning.") # post.title += "!" # post.save # => saves both post and 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 # => [#, # # 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 module AutosaveAssociation extend ActiveSupport::Concern module AssociationBuilderExtension # nodoc: def self.build: (untyped model, untyped reflection) -> untyped def self.valid_options: () -> ::Array[:autosave] end module ClassMethods def define_non_cyclic_method: (untyped name) { () -> untyped } -> (nil | untyped) # Adds validation and save callbacks for the association as specified by # the +reflection+. # # For performance reasons, we don't check whether to validate at runtime. # However the validation and callback methods are lazy and those methods # get created when they are invoked for the very first time. However, # this can change, for instance, when using nested attributes, which is # called _after_ the association has been defined. Since we don't want # the callbacks to get defined multiple times, there are guards that # check if the save or validation methods have already been defined # before actually defining them. def add_autosave_association_callbacks: (untyped reflection) -> untyped def define_autosave_validation_callbacks: (untyped reflection) -> untyped end # Reloads the attributes of the object as usual and clears marked_for_destruction flag. def reload: (?untyped? options) -> untyped # 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. def mark_for_destruction: () -> untyped # 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. def marked_for_destruction?: () -> untyped # Records the association that is being destroyed and destroying this # record in the process. def destroyed_by_association=: (untyped reflection) -> untyped # Returns the association for the parent being destroyed. # # Used to avoid updating the counter cache unnecessarily. def destroyed_by_association: () -> untyped # Returns whether or not this record has been changed in any way (including whether # any of its nested autosave associations are likewise changed) def changed_for_autosave?: () -> untyped # Returns the record for an association collection that should be validated # or saved. If +autosave+ is +false+ only new records will be returned, # unless the parent is/was a new record itself. def associated_records_to_validate_or_save: (untyped association, untyped new_record, untyped autosave) -> untyped # go through nested autosave associations that are loaded in memory (without loading # any new ones), and return true if is changed for autosave def nested_records_changed_for_autosave?: () -> (::FalseClass | untyped) # Validate the association if :validate or :autosave is # turned on for the association. def validate_single_association: (untyped reflection) -> untyped # Validate the associated records if :validate or # :autosave is turned on for the association specified by # +reflection+. def validate_collection_association: (untyped reflection) -> untyped # Returns whether or not the association is valid and applies any errors to # the parent, self, if it wasn't. Skips any :autosave # enabled records if they're marked_for_destruction? or destroyed. def association_valid?: (untyped reflection, untyped record, ?untyped? index) -> (::TrueClass | untyped) def normalize_reflection_attribute: (untyped indexed_attribute, untyped reflection, untyped index, untyped attribute) -> untyped # Is used as a before_save callback to check while saving a collection # association whether or not the parent was a new record before saving. def before_save_collection_association: () -> untyped def after_save_collection_association: () -> untyped # Saves any new associated records, or all loaded autosave associations if # :autosave is enabled on the association. # # In addition, it destroys all children that were marked for destruction # with #mark_for_destruction. # # This all happens inside a transaction, _if_ the Transactions module is included into # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_collection_association: (untyped reflection) -> untyped # Saves the associated record if it's new or :autosave is enabled # on the association. # # In addition, it will destroy the association if it was marked for # destruction with #mark_for_destruction. # # This all happens inside a transaction, _if_ the Transactions module is included into # ActiveRecord::Base after the AutosaveAssociation module, which it does by default. def save_has_one_association: (untyped reflection) -> untyped # If the record is new or it has changed, returns true. def record_changed?: (untyped reflection, untyped record, untyped key) -> untyped def association_foreign_key_changed?: (untyped reflection, untyped record, untyped key) -> (::FalseClass | untyped) # Saves the associated record if it's new or :autosave is enabled. # # In addition, it will destroy the association if it was marked for destruction. def save_belongs_to_association: (untyped reflection) -> (nil | untyped) def custom_validation_context?: () -> untyped def _ensure_no_duplicate_errors: () -> untyped end end module ActiveRecord # nodoc: # = 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 link: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 # # == 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 _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}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#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}[rdoc-ref:ConnectionHandling#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}[rdoc-ref:ConnectionHandling#retrieve_connection] method # will go up the class-hierarchy until a connection is found in the connection pool. # # == Exceptions # # * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record. # * AdapterNotSpecified - The configuration hash used in # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] # didn't include an :adapter key. # * AdapterNotFound - The :adapter key used in # {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] # specified a non-existent adapter # (or a bad spelling of an existing one). # * AssociationTypeMismatch - The object assigned to the association wasn't of the type # specified in the association definition. # * AttributeAssignmentError - An error occurred while doing a mass assignment through the # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method. # You can inspect the +attribute+ property of the exception object to determine which attribute # triggered the error. # * ConnectionNotEstablished - No connection has been established. # Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying. # * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method. # The +errors+ property of this exception contains an array of # AttributeAssignmentError # objects that should be inspected to determine which attributes triggered the errors. # * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!] # when the record is invalid. # * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method. # Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions. # Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal # nothing was found, please check its documentation for further details. # * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter. # * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message. # # *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. class Base extend ActiveModel::Naming extend ActiveSupport::Benchmarkable extend ActiveSupport::DescendantsTracker extend ConnectionHandling extend QueryCache::ClassMethods extend Querying extend Translation extend DynamicMatchers extend Explain extend Enum extend Delegation::DelegateCache extend Aggregations::ClassMethods include Core extend ::ActiveRecord::Core::ClassMethods include Persistence extend ::ActiveRecord::Persistence::ClassMethods include ReadonlyAttributes extend ::ActiveRecord::ReadonlyAttributes::ClassMethods include ModelSchema extend ::ActiveRecord::ModelSchema::ClassMethods include Inheritance extend ::ActiveRecord::Inheritance::ClassMethods include Scoping extend ::ActiveRecord::Scoping::ClassMethods include Sanitization extend ::ActiveRecord::Sanitization::ClassMethods include AttributeAssignment include ActiveModel::Conversion extend ::ActiveModel::Conversion::ClassMethods include Integration extend ::ActiveRecord::Integration::ClassMethods include Validations extend ::ActiveRecord::Validations::ClassMethods include CounterCache extend ::ActiveRecord::CounterCache::ClassMethods include Attributes extend ::ActiveRecord::Attributes::ClassMethods include AttributeDecorators extend ::ActiveRecord::AttributeDecorators::ClassMethods include Locking::Optimistic extend ::ActiveRecord::Locking::Optimistic::ClassMethods include Locking::Pessimistic include DefineCallbacks extend ::ActiveRecord::DefineCallbacks::ClassMethods include AttributeMethods extend ::ActiveRecord::AttributeMethods::ClassMethods include Callbacks include Timestamp extend ::ActiveRecord::Timestamp::ClassMethods include Associations extend ::ActiveRecord::Associations::ClassMethods include ActiveModel::SecurePassword extend ::ActiveModel::SecurePassword::ClassMethods include AutosaveAssociation extend ::ActiveRecord::AutosaveAssociation::ClassMethods include NestedAttributes extend ::ActiveRecord::NestedAttributes::ClassMethods include Transactions extend ::ActiveRecord::Transactions::ClassMethods include TouchLater include NoTouching extend ::ActiveRecord::NoTouching::ClassMethods include Reflection extend ::ActiveRecord::Reflection::ClassMethods include Serialization include Store extend ::ActiveRecord::Store::ClassMethods include SecureToken extend ::ActiveRecord::SecureToken::ClassMethods include Suppressor extend ::ActiveRecord::Suppressor::ClassMethods end end module ActiveRecord # = Active Record \Callbacks # # \Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic # before or after an alteration of the object state. This can be used to make sure that associated and # dependent objects are deleted when {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#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}[rdoc-ref:Persistence#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 you immense power to react and prepare for each state in the # Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#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 down through an inheritance hierarchy. # # class Topic < ActiveRecord::Base # before_destroy :destroy_author # end # # class Reply < Topic # before_destroy :destroy_readers # end # # Now, 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 four 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}[rdoc-ref:Persistence#save] will return +false+. # If {ActiveRecord::Base#save!}[rdoc-ref:Persistence#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 the code needs that the callbacks execute in a specific order. For example, a +before_destroy+ # callback (+log_children+ in this case) should be executed before the children get 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, the children are not available # because the {ActiveRecord::Base#destroy}[rdoc-ref:Persistence#destroy] callback gets 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+ gets 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+ gets executed before +do_something_else+. # The same applies to all non-transactional callbacks. # # In case there are multiple transactional callbacks as seen below, 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+ gets executed before +log_children+. # # == \Transactions # # The entire callback chain of a {#save}[rdoc-ref:Persistence#save], {#save!}[rdoc-ref:Persistence#save!], # or {#destroy}[rdoc-ref:Persistence#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}[rdoc-ref:Persistence#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. # module Callbacks extend ActiveSupport::Concern CALLBACKS: ::Array[untyped] def destroy: () -> untyped def touch: () -> untyped def increment!: (untyped attribute, ?::Integer by, ?touch: untyped? touch) -> untyped def create_or_update: () -> untyped def _create_record: () -> untyped def _update_record: () -> untyped end end module ActiveRecord module Coders class JSON # :nodoc: # :nodoc: def self.dump: (untyped obj) -> untyped def self.load: (untyped json) -> untyped end end end module ActiveRecord module Coders class YAMLColumn # :nodoc: # :nodoc: attr_accessor object_class: untyped def initialize: (untyped attr_name, ?untyped object_class) -> untyped def dump: (untyped obj) -> (nil | untyped) def load: (untyped yaml) -> untyped def assert_valid_value: (untyped obj, action: untyped action) -> untyped def check_arity_of_constructor: () -> untyped end end end module ActiveRecord module ConnectionAdapters # :nodoc: extend ActiveSupport::Autoload # 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}[rdoc-ref:ConnectionHandling#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. class AbstractAdapter ADAPTER_NAME: ::String include ActiveSupport::Callbacks extend ::ActiveSupport::Callbacks::ClassMethods include Quoting include DatabaseStatements include SchemaStatements include DatabaseLimits include QueryCache include Savepoints SIMPLE_INT: untyped COMMENT_REGEX: untyped attr_accessor pool: untyped attr_reader visitor: untyped attr_reader owner: untyped attr_reader logger: untyped attr_reader lock: untyped def self.type_cast_config_to_integer: (untyped config) -> untyped def self.type_cast_config_to_boolean: (untyped config) -> untyped def self.build_read_query_regexp: (*untyped parts) -> ::Regexp def self.quoted_column_names: () -> untyped def self.quoted_table_names: () -> untyped def initialize: (untyped connection, ?untyped? logger, ?::Hash[untyped, untyped] config) -> untyped def replica?: () -> untyped # Determines whether writes are currently being prevents. # # Returns true if the connection is a replica, or if +prevent_writes+ # is set to true. def preventing_writes?: () -> untyped def migrations_paths: () -> untyped def migration_context: () -> MigrationContext def schema_migration: () -> untyped def prepared_statements: () -> untyped def prepared_statements_disabled_cache: () -> untyped class Version include Comparable attr_reader full_version_string: untyped def initialize: (untyped version_string, ?untyped? full_version_string) -> untyped def <=>: (untyped version_string) -> untyped def to_s: () -> untyped end def valid_type?: (untyped `type`) -> untyped # this method must only be called while holding connection pool's mutex def lease: () -> untyped def schema_cache: () -> untyped def schema_cache=: (untyped cache) -> untyped # this method must only be called while holding connection pool's mutex def expire: () -> untyped def steal!: () -> untyped def seconds_idle: () -> (0 | untyped) def unprepared_statement: () { () -> untyped } -> untyped # Returns the human-readable name of the adapter. Use mixed case - one # can always use downcase if needed. def adapter_name: () -> untyped # Does the database for this adapter exist? def self.database_exists?: (untyped config) -> untyped # Does this adapter support DDL rollbacks in transactions? That is, would # CREATE TABLE or ALTER TABLE get rolled back by a transaction? def supports_ddl_transactions?: () -> ::FalseClass def supports_bulk_alter?: () -> ::FalseClass # Does this adapter support savepoints? def supports_savepoints?: () -> ::FalseClass # Does this adapter support application-enforced advisory locking? def supports_advisory_locks?: () -> ::FalseClass # 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. def prefetch_primary_key?: (?untyped? table_name) -> ::FalseClass def supports_partitioned_indexes?: () -> ::FalseClass # Does this adapter support index sort order? def supports_index_sort_order?: () -> ::FalseClass # Does this adapter support partial indices? def supports_partial_index?: () -> ::FalseClass # Does this adapter support expression indices? def supports_expression_index?: () -> ::FalseClass # Does this adapter support explain? def supports_explain?: () -> ::FalseClass # Does this adapter support setting the isolation level for a transaction? def supports_transaction_isolation?: () -> ::FalseClass # Does this adapter support database extensions? def supports_extensions?: () -> ::FalseClass # Does this adapter support creating indexes in the same statement as # creating the table? def supports_indexes_in_create?: () -> ::FalseClass # Does this adapter support creating foreign key constraints? def supports_foreign_keys?: () -> ::FalseClass # Does this adapter support creating invalid constraints? def supports_validate_constraints?: () -> ::FalseClass # Does this adapter support creating foreign key constraints # in the same statement as creating the table? def supports_foreign_keys_in_create?: () -> untyped # Does this adapter support views? def supports_views?: () -> ::FalseClass # Does this adapter support materialized views? def supports_materialized_views?: () -> ::FalseClass # Does this adapter support datetime with precision? def supports_datetime_with_precision?: () -> ::FalseClass # Does this adapter support json data type? def supports_json?: () -> ::FalseClass # Does this adapter support metadata comments on database objects (tables, columns, indexes)? def supports_comments?: () -> ::FalseClass # Can comments for tables, columns, and indexes be specified in create/alter table statements? def supports_comments_in_create?: () -> ::FalseClass # Does this adapter support multi-value insert? def supports_multi_insert?: () -> ::TrueClass # Does this adapter support virtual columns? def supports_virtual_columns?: () -> ::FalseClass # Does this adapter support foreign/external tables? def supports_foreign_tables?: () -> ::FalseClass # Does this adapter support optimizer hints? def supports_optimizer_hints?: () -> ::FalseClass def supports_common_table_expressions?: () -> ::FalseClass def supports_lazy_transactions?: () -> ::FalseClass def supports_insert_returning?: () -> ::FalseClass def supports_insert_on_duplicate_skip?: () -> ::FalseClass def supports_insert_on_duplicate_update?: () -> ::FalseClass def supports_insert_conflict_target?: () -> ::FalseClass # This is meant to be implemented by the adapters that support extensions def disable_extension: (untyped name) -> nil # This is meant to be implemented by the adapters that support extensions def enable_extension: (untyped name) -> nil def advisory_locks_enabled?: () -> untyped def get_advisory_lock: (untyped lock_id) -> nil def release_advisory_lock: (untyped lock_id) -> nil # A list of extensions, to be filled in by adapters that support them. def extensions: () -> ::Array[untyped] # A list of index algorithms, to be filled by adapters that support them. def index_algorithms: () -> ::Hash[untyped, untyped] # Override to turn off referential integrity while executing &block. def disable_referential_integrity: () { () -> untyped } -> untyped # 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. def active?: () -> nil # 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. def reconnect!: () -> untyped # Disconnects from the database if already connected. Otherwise, this # method does nothing. def disconnect!: () -> untyped # 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. def discard!: () -> untyped # 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. def reset!: () -> nil # Clear any caching the database adapter may be doing. def clear_cache!: () -> untyped # Returns true if its required to reload the connection between requests for development mode. def requires_reloading?: () -> ::FalseClass # 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. def verify!: () -> untyped # 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. def raw_connection: () -> untyped def default_uniqueness_comparison: (untyped attribute, untyped value, untyped klass) -> untyped def case_sensitive_comparison: (untyped attribute, untyped value) -> untyped def case_insensitive_comparison: (untyped attribute, untyped value) -> untyped def can_perform_case_insensitive_comparison_for?: (untyped column) -> ::TrueClass # Check the connection back in to the connection pool def close: () -> untyped def column_name_for_operation: (untyped operation, untyped node) -> untyped def default_index_type?: (untyped index) -> untyped def build_insert_sql: (untyped insert) -> ::String def get_database_version: () -> nil def database_version: () -> untyped def check_version: () -> nil def type_map: () -> untyped def initialize_type_map: (?untyped m) -> untyped def reload_type_map: () -> untyped def register_class_with_limit: (untyped mapping, untyped key, untyped klass) -> untyped def register_class_with_precision: (untyped mapping, untyped key, untyped klass) -> untyped def extract_scale: (untyped sql_type) -> untyped def extract_precision: (untyped sql_type) -> untyped def extract_limit: (untyped sql_type) -> untyped def translate_exception_class: (untyped e, untyped sql, untyped binds) -> untyped def log: (untyped sql, ?::String name, ?untyped binds, ?untyped type_casted_binds, ?untyped? statement_name) { () -> untyped } -> untyped def translate_exception: (untyped exception, binds: untyped binds, sql: untyped sql, message: untyped message) -> untyped def without_prepared_statement?: (untyped binds) -> untyped def column_for: (untyped table_name, untyped column_name) -> untyped def column_for_attribute: (untyped attribute) -> untyped def collector: () -> untyped def arel_visitor: () -> Arel::Visitors::ToSql def build_statement_pool: () -> nil end end end module ActiveRecord # Raised when a connection could not be obtained within the connection # acquisition timeout period: because max connections in pool # are in use. class ConnectionTimeoutError < ConnectionNotEstablished end # 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!}[rdoc-ref:ConnectionAdapters::ConnectionPool#disconnect!] # or {ActiveRecord::Base.clear_reloadable_connections!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#clear_reloadable_connections!]. class ExclusiveConnectionTimeoutError < ConnectionTimeoutError end module ConnectionAdapters module AbstractPool # :nodoc: def get_schema_cache: (untyped connection) -> untyped def set_schema_cache: (untyped cache) -> untyped end class NullPool # :nodoc: include ConnectionAdapters::AbstractPool def initialize: () -> untyped end # 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}[rdoc-ref:ConnectionHandling.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!}[rdoc-ref:ConnectionAdapters::ConnectionHandler#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}[rdoc-ref:#checkout]. You are responsible for # returning this connection to the pool when finished by calling # {ActiveRecord::Base.connection_pool.checkin(connection)}[rdoc-ref:#checkin]. # 3. Use {ActiveRecord::Base.connection_pool.with_connection(&block)}[rdoc-ref:#with_connection], 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). # # - # Synchronization policy: # * all public methods can be called outside +synchronize+ # * access to these instance variables needs to be in +synchronize+: # * @connections # * @now_connecting # * private methods that require being called in a +synchronize+ blocks # are now explicitly documented class ConnectionPool # Threadsafe, fair, LIFO queue. Meant to be used by ConnectionPool # with which it shares a Monitor. class Queue def initialize: (?untyped lock) -> untyped # Test if any threads are currently waiting on the queue. def any_waiting?: () -> untyped # Returns the number of threads currently waiting on this # queue. def num_waiting: () -> untyped # Add +element+ to the queue. Never blocks. def add: (untyped element) -> untyped # If +element+ is in the queue, remove and return it, or +nil+. def delete: (untyped element) -> untyped # Remove all elements from the queue. def clear: () -> untyped # Remove the head of the queue. # # If +timeout+ is not given, remove and return the head 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: # - ActiveRecord::ConnectionTimeoutError if +timeout+ is given and no element # becomes available within +timeout+ seconds, def poll: (?untyped? timeout) -> untyped def internal_poll: (untyped timeout) -> untyped def synchronize: () { () -> untyped } -> untyped # Test if the queue currently contains any elements. def any?: () -> untyped # A thread can remove an element from the queue without # waiting if and only if the number of currently available # connections is strictly greater than the number of waiting # threads. def can_remove_no_wait?: () -> untyped # Removes and returns the head of the queue if possible, or +nil+. def remove: () -> untyped # Remove and return the head the queue if the number of # available elements is strictly greater than the number of # threads currently waiting. Otherwise, return +nil+. def no_wait_poll: () -> untyped # Waits on the queue up to +timeout+ seconds, then removes and # returns the head of the queue. def wait_poll: (untyped timeout) -> untyped end module BiasableQueue class BiasedConditionVariable # Adds the ability to turn a basic fair FIFO queue into one # biased to some thread. # :nodoc: # :nodoc: # semantics of condition variables guarantee that +broadcast+, +broadcast_on_biased+, # +signal+ and +wait+ methods are only called while holding a lock def initialize: (untyped lock, untyped other_cond, untyped preferred_thread) -> untyped def broadcast: () -> untyped def broadcast_on_biased: () -> untyped def signal: () -> untyped def wait: (untyped timeout) -> untyped end def with_a_bias_for: (untyped thread) { () -> untyped } -> untyped end class ConnectionLeasingQueue < Queue # Connections must be leased while holding the main pool mutex. This is # an internal subclass that also +.leases+ returned connections while # still in queue's critical section (queue synchronizes with the same # @lock as the main pool) so that a returned connection is already # leased and there is no need to re-enter synchronized block. # :nodoc: include BiasableQueue def internal_poll: (untyped timeout) -> untyped end # 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). class Reaper attr_reader pool: untyped attr_reader frequency: untyped def initialize: (untyped pool, untyped frequency) -> untyped def self.register_pool: (untyped pool, untyped frequency) -> untyped def self.spawn_thread: (untyped frequency) -> untyped def run: () -> (nil | untyped) end include MonitorMixin include QueryCache::ConnectionPoolConfiguration include ConnectionAdapters::AbstractPool attr_accessor automatic_reconnect: untyped attr_accessor checkout_timeout: untyped attr_accessor schema_cache: untyped attr_reader spec: untyped attr_reader size: untyped attr_reader reaper: untyped # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification # 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. def initialize: (untyped spec) -> untyped def lock_thread=: (untyped lock_thread) -> untyped # 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. def connection: () -> untyped # 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? def active_connection?: () -> untyped # 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. def release_connection: (?untyped owner_thread) -> untyped # 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. def with_connection: () { (untyped) -> untyped } -> untyped # Returns true if a connection has already been opened. def connected?: () -> untyped # 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. def connections: () -> untyped # Disconnects all connections in the pool, and clears the pool. # # Raises: # - ActiveRecord::ExclusiveConnectionTimeoutError if unable to gain ownership of all # connections in the pool within a timeout interval (default duration is # spec.config[:checkout_timeout] * 2 seconds). def disconnect: (?bool raise_on_acquisition_timeout) -> untyped # 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.config[:checkout_timeout] * 2 seconds), then the pool is forcefully # disconnected without any regard for other connection owning threads. def disconnect!: () -> untyped def discard!: () -> untyped # Clears the cache which maps classes and re-connects connections that # require reloading. # # Raises: # - ActiveRecord::ExclusiveConnectionTimeoutError if unable to gain ownership of all # connections in the pool within a timeout interval (default duration is # spec.config[:checkout_timeout] * 2 seconds). def clear_reloadable_connections: (?bool raise_on_acquisition_timeout) -> untyped # 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.config[:checkout_timeout] * 2 seconds), then the pool forcefully # clears the cache and reloads connections without any regard for other # connection owning threads. def clear_reloadable_connections!: () -> untyped # 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: # - ActiveRecord::ConnectionTimeoutError no connection can be obtained from the pool. def checkout: (?untyped checkout_timeout) -> untyped # 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. def checkin: (untyped conn) -> untyped # Remove a connection from the connection pool. The connection will # remain open and active but will no longer be managed by this pool. def remove: (untyped conn) -> untyped # 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. def reap: () -> (nil | untyped) # 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. def flush: (?untyped minimum_idle) -> (nil | untyped) # Disconnect all currently idle connections. Connections currently checked # out are unaffected. def flush!: () -> untyped def num_waiting_in_queue: () -> untyped # 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 } def stat: () -> untyped # - # this is unfortunately not concurrent def bulk_make_new_connections: (untyped num_new_conns_needed) -> untyped # - # From the discussion on GitHub: # https://github.com/rails/rails/pull/14938#commitcomment-6601951 # This hook-in method allows for easier monkey-patching fixes needed by # JRuby users that use Fibers. def connection_cache_key: (untyped thread) -> untyped def current_thread: () -> untyped # Take control of all existing connections so a "group" action such as # reload/disconnect can be performed safely. It is no longer enough to # wrap it in +synchronize+ because some pool's actions are allowed # to be performed outside of the main +synchronize+ block. def with_exclusively_acquired_all_connections: (?bool raise_on_acquisition_timeout) { () -> untyped } -> untyped def attempt_to_checkout_all_existing_connections: (?bool raise_on_acquisition_timeout) -> untyped # - # Must be called in a synchronize block. def checkout_for_exclusive_access: (untyped checkout_timeout) -> untyped def with_new_connections_blocked: () { () -> untyped } -> untyped # Acquire a connection by one of 1) immediately removing one # from the queue of available connections, 2) creating a new # connection if the pool is not at capacity, 3) waiting on the # queue for a connection to become available. # # Raises: # - ActiveRecord::ConnectionTimeoutError if a connection could not be acquired # # - # Implementation detail: the connection returned by +acquire_connection+ # will already be "+connection.lease+ -ed" to the current thread. def acquire_connection: (untyped checkout_timeout) -> untyped # - # if owner_thread param is omitted, this must be called in synchronize block def remove_connection_from_thread_cache: (untyped conn, ?untyped owner_thread) -> untyped def new_connection: () -> untyped # If the pool is not at a @size limit, establish new connection. Connecting # to the DB is done outside main synchronized section. # - # Implementation constraint: a newly established connection returned by this # method must be in the +.leased+ state. def try_to_checkout_new_connection: () -> untyped def adopt_connection: (untyped conn) -> untyped def checkout_new_connection: () -> untyped def checkout_and_verify: (untyped c) -> untyped end # 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 specification name to the handler, # in order to look up the correct connection pool. class ConnectionHandler def self.create_owner_to_pool: () -> untyped def self.unowned_pool_finalizer: (untyped pid_map) -> untyped def self.discard_unowned_pools: (untyped pid_map) -> untyped def initialize: () -> untyped def prevent_writes: () -> untyped def prevent_writes=: (untyped prevent_writes) -> untyped # 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. def while_preventing_writes: (?bool enabled) { () -> untyped } -> untyped def connection_pool_list: () -> untyped def establish_connection: (untyped config) -> untyped # Returns true if there are any active connections among the connection # pools that the ConnectionHandler is managing. def active_connections?: () -> untyped # 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. def clear_active_connections!: () -> untyped # Clears the cache which maps classes. # # See ConnectionPool#clear_reloadable_connections! for details. def clear_reloadable_connections!: () -> untyped def clear_all_connections!: () -> untyped # Disconnects all currently idle connections. # # See ConnectionPool#flush! for details. def flush_idle_connections!: () -> untyped def retrieve_connection: (untyped spec_name) -> untyped # Returns true if a connection that's accessible to this class has # already been opened. def connected?: (untyped spec_name) -> untyped # Remove the connection for this class. This will close the active # connection and the defined connection (if they exist). The result # can be used as an argument for #establish_connection, for easily # re-establishing the connection. def remove_connection: (untyped spec_name) -> untyped # Retrieving the connection pool happens a lot, so we cache it in @owner_to_pool. # This makes retrieving the connection pool O(1) once the process is warm. # When a connection is established or removed, we invalidate the cache. def retrieve_connection_pool: (untyped spec_name) -> untyped def owner_to_pool: () -> untyped def pool_from_any_process_for: (untyped spec_name) -> untyped end end end module ActiveRecord module ConnectionAdapters # :nodoc: module DatabaseLimits def max_identifier_length: () -> 64 # Returns the maximum length of a table alias. def table_alias_length: () -> untyped # Returns the maximum length of a column name. def column_name_length: () -> untyped # Returns the maximum length of a table name. def table_name_length: () -> untyped # Returns the maximum allowed length for an index name. This # limit is enforced by \Rails and is less than or equal to # #index_name_length. The gap between # #index_name_length is to allow internal \Rails # operations to use prefixes in temporary operations. def allowed_index_name_length: () -> untyped # Returns the maximum length of an index name. def index_name_length: () -> untyped # Returns the maximum number of columns per table. def columns_per_table: () -> 1024 # Returns the maximum number of indexes per table. def indexes_per_table: () -> 16 # Returns the maximum number of columns in a multicolumn index. def columns_per_multicolumn_index: () -> 16 # Returns the maximum number of elements in an IN (x,y,z) clause. # +nil+ means no limit. def in_clause_length: () -> nil # Returns the maximum length of an SQL query. def sql_query_length: () -> 1048575 # Returns maximum number of joins in a single query. def joins_per_query: () -> 256 def bind_params_length: () -> 65535 end end end module ActiveRecord module ConnectionAdapters # :nodoc: module DatabaseStatements def initialize: () -> untyped # Converts an arel AST to SQL def to_sql: (untyped arel_or_sql_string, ?untyped binds) -> untyped def to_sql_and_binds: (untyped arel_or_sql_string, ?untyped binds) -> untyped def cacheable_query: (untyped klass, untyped arel) -> ::Array[untyped] # Returns an ActiveRecord::Result instance. def select_all: (untyped arel, ?untyped? name, ?untyped binds, ?preparable: untyped? preparable) -> untyped # Returns a record hash with the column names as keys and column values # as values. def select_one: (untyped arel, ?untyped? name, ?untyped binds) -> untyped # Returns a single value from a record def select_value: (untyped arel, ?untyped? name, ?untyped binds) -> untyped # Returns an array of the values of the first column in a select: # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3] def select_values: (untyped arel, ?untyped? name, ?untyped binds) -> untyped # Returns an array of arrays containing the field values. # Order is the same as that returned by +columns+. def select_rows: (untyped arel, ?untyped? name, ?untyped binds) -> untyped def query_value: (untyped sql, ?untyped? name) -> untyped def query_values: (untyped sql, ?untyped? name) -> untyped def query: (untyped sql, ?untyped? name) -> untyped # Determines whether the SQL statement is a write query. def write_query?: (untyped sql) -> untyped # 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. def execute: (untyped sql, ?untyped? name) -> untyped # Executes +sql+ statement in the context of this connection using # +binds+ as the bind substitutes. +name+ is logged along with # the executed +sql+ statement. def exec_query: (untyped sql, ?::String name, ?untyped binds, ?prepare: bool prepare) -> untyped # 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. def exec_insert: (untyped sql, ?untyped? name, ?untyped binds, ?untyped? pk, ?untyped? sequence_name) -> untyped # 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. def exec_delete: (untyped sql, ?untyped? name, ?untyped binds) -> untyped # 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. def exec_update: (untyped sql, ?untyped? name, ?untyped binds) -> untyped def exec_insert_all: (untyped sql, untyped name) -> untyped # 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+. def insert: (untyped arel, ?untyped? name, ?untyped? pk, ?untyped? id_value, ?untyped? sequence_name, ?untyped binds) -> untyped # Executes the update statement and returns the number of rows affected. def update: (untyped arel, ?untyped? name, ?untyped binds) -> untyped # Executes the delete statement and returns the number of rows affected. def delete: (untyped arel, ?untyped? name, ?untyped binds) -> untyped # Executes the truncate statement. def truncate: (untyped table_name, ?untyped? name) -> untyped def truncate_tables: (*untyped table_names) -> (nil | untyped) # Runs the given block in a database transaction, and returns the result # of the block. # # == Nested transactions support # # 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: # https://dev.mysql.com/doc/refman/5.7/en/savepoint.html # Savepoints are supported by MySQL and PostgreSQL. SQLite3 version >= '3.6.8' # supports savepoints. # # 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. # # === 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: # # * https://www.postgresql.org/docs/current/static/transaction-iso.html # * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html # # 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. def transaction: (?joinable: bool joinable, ?isolation: untyped? isolation, ?requires_new: untyped? requires_new) { () -> untyped } -> untyped attr_reader transaction_manager: untyped def transaction_open?: () -> untyped def reset_transaction: () -> untyped # Register a record with the current transaction so that its after_commit and after_rollback callbacks # can be called. def add_transaction_record: (untyped record) -> untyped def transaction_state: () -> untyped # Begins the transaction (and turns off auto-committing). def begin_db_transaction: () -> nil def transaction_isolation_levels: () -> { read_uncommitted: "READ UNCOMMITTED", read_committed: "READ COMMITTED", repeatable_read: "REPEATABLE READ", serializable: "SERIALIZABLE" } # Begins the transaction with the isolation level set. Raises an error by # default; adapters that support setting the isolation level should implement # this method. def begin_isolated_db_transaction: (untyped isolation) -> untyped # Commits the transaction (and turns on auto-committing). def commit_db_transaction: () -> nil # Rolls back the transaction (and turns on auto-committing). Must be # done if the transaction block raises an exception or returns false. def rollback_db_transaction: () -> untyped def exec_rollback_db_transaction: () -> nil def rollback_to_savepoint: (?untyped? name) -> untyped def default_sequence_name: (untyped table, untyped column) -> nil # Set the sequence to the max value of the table's column. def reset_sequence!: (untyped table, untyped column, ?untyped? sequence) -> nil # Inserts the given fixture into the table. Overridden in adapters that require # something beyond a simple insert (eg. 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. def insert_fixture: (untyped fixture, untyped table_name) -> untyped def insert_fixtures_set: (untyped fixture_set, ?untyped tables_to_delete) -> untyped def empty_insert_statement_value: (?untyped? primary_key) -> "DEFAULT VALUES" # 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. def sanitize_limit: (untyped limit) -> untyped def with_yaml_fallback: (untyped value) -> untyped def execute_batch: (untyped statements, ?untyped? name) -> untyped DEFAULT_INSERT_VALUE: untyped def default_insert_value: (untyped column) -> untyped def build_fixture_sql: (untyped fixtures, untyped table_name) -> untyped def build_fixture_statements: (untyped fixture_set) -> untyped def build_truncate_statement: (untyped table_name) -> ::String def build_truncate_statements: (untyped table_names) -> untyped def with_multi_statements: () { () -> untyped } -> untyped def combine_multi_statements: (untyped total_sql) -> untyped # Returns an ActiveRecord::Result instance. def select: (untyped sql, ?untyped? name, ?untyped binds) -> untyped def select_prepared: (untyped sql, ?untyped? name, ?untyped binds) -> untyped def sql_for_insert: (untyped sql, untyped pk, untyped binds) -> ::Array[untyped] def last_inserted_id: (untyped result) -> untyped def single_value_from_rows: (untyped rows) -> untyped def arel_from_relation: (untyped relation) -> untyped end end end module ActiveRecord module ConnectionAdapters class AbstractMysqlAdapter < AbstractAdapter include MySQL::Quoting include MySQL::SchemaStatements NATIVE_DATABASE_TYPES: ::Hash[untyped, untyped] class StatementPool < ConnectionAdapters::StatementPool def dealloc: (untyped stmt) -> untyped end def initialize: (untyped connection, untyped logger, untyped connection_options, untyped config) -> untyped def get_database_version: () -> AbstractAdapter::Version def mariadb?: () -> untyped def supports_bulk_alter?: () -> ::TrueClass def supports_index_sort_order?: () -> untyped def supports_expression_index?: () -> untyped def supports_transaction_isolation?: () -> ::TrueClass def supports_explain?: () -> ::TrueClass def supports_indexes_in_create?: () -> ::TrueClass def supports_foreign_keys?: () -> ::TrueClass def supports_views?: () -> ::TrueClass def supports_datetime_with_precision?: () -> untyped def supports_virtual_columns?: () -> untyped # See https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html for more details. def supports_optimizer_hints?: () -> untyped def supports_common_table_expressions?: () -> untyped def supports_advisory_locks?: () -> ::TrueClass def supports_insert_on_duplicate_skip?: () -> ::TrueClass def supports_insert_on_duplicate_update?: () -> ::TrueClass def get_advisory_lock: (untyped lock_name, ?::Integer timeout) -> untyped def release_advisory_lock: (untyped lock_name) -> untyped def native_database_types: () -> untyped def index_algorithms: () -> { default: untyped, copy: untyped, inplace: untyped } def each_hash: (untyped result) -> untyped def error_number: (untyped exception) -> untyped def disable_referential_integrity: () { () -> untyped } -> untyped def clear_cache!: () -> untyped def explain: (untyped arel, ?untyped binds) -> untyped # Executes the SQL statement in the context of this connection. def execute: (untyped sql, ?untyped? name) -> untyped def execute_and_free: (untyped sql, ?untyped? name) { (untyped) -> untyped } -> untyped def begin_db_transaction: () -> untyped def begin_isolated_db_transaction: (untyped isolation) -> untyped def commit_db_transaction: () -> untyped def exec_rollback_db_transaction: () -> untyped def empty_insert_statement_value: (?untyped? primary_key) -> "VALUES ()" # Drops the database specified on the +name+ attribute # and creates it again using the provided +options+. def recreate_database: (untyped name, ?::Hash[untyped, untyped] options) -> untyped # 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 def create_database: (untyped name, ?::Hash[untyped, untyped] options) -> untyped def drop_database: (untyped name) -> untyped def current_database: () -> untyped # Returns the database character set. def charset: () -> untyped # Returns the database collation strategy. def collation: () -> untyped def table_comment: (untyped table_name) -> untyped def change_table_comment: (untyped table_name, untyped comment_or_changes) -> untyped # Renames a table. # # Example: # rename_table('octopuses', 'octopi') def rename_table: (untyped table_name, untyped new_name) -> untyped # 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. def drop_table: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped def rename_index: (untyped table_name, untyped old_name, untyped new_name) -> untyped def change_column_default: (untyped table_name, untyped column_name, untyped default_or_changes) -> untyped def change_column_null: (untyped table_name, untyped column_name, untyped null, ?untyped? default) -> untyped def change_column_comment: (untyped table_name, untyped column_name, untyped comment_or_changes) -> untyped def change_column: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def rename_column: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped def add_index: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> untyped def add_sql_comment!: (untyped sql, untyped comment) -> untyped def foreign_keys: (untyped table_name) -> untyped def table_options: (untyped table_name) -> untyped # SHOW VARIABLES LIKE 'name' def show_variable: (untyped name) -> untyped def primary_keys: (untyped table_name) -> untyped def default_uniqueness_comparison: (untyped attribute, untyped value, untyped klass) -> untyped def case_sensitive_comparison: (untyped attribute, untyped value) -> untyped def can_perform_case_insensitive_comparison_for?: (untyped column) -> untyped def columns_for_distinct: (untyped columns, untyped orders) -> untyped def strict_mode?: () -> untyped def default_index_type?: (untyped index) -> untyped def build_insert_sql: (untyped insert) -> untyped def check_version: () -> untyped def initialize_type_map: (?untyped m) -> untyped def register_integer_type: (untyped mapping, untyped key, **untyped options) -> untyped def extract_precision: (untyped sql_type) -> untyped # See https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html ER_FILSORT_ABORT: ::Integer ER_DUP_ENTRY: ::Integer ER_NOT_NULL_VIOLATION: ::Integer ER_NO_REFERENCED_ROW: ::Integer ER_ROW_IS_REFERENCED: ::Integer ER_DO_NOT_HAVE_DEFAULT: ::Integer ER_ROW_IS_REFERENCED_2: ::Integer ER_NO_REFERENCED_ROW_2: ::Integer ER_DATA_TOO_LONG: ::Integer ER_OUT_OF_RANGE: ::Integer ER_LOCK_DEADLOCK: ::Integer ER_CANNOT_ADD_FOREIGN: ::Integer ER_CANNOT_CREATE_TABLE: ::Integer ER_LOCK_WAIT_TIMEOUT: ::Integer ER_QUERY_INTERRUPTED: ::Integer ER_QUERY_TIMEOUT: ::Integer ER_FK_INCOMPATIBLE_COLUMNS: ::Integer def translate_exception: (untyped exception, binds: untyped binds, sql: untyped sql, message: untyped message) -> untyped def change_column_for_alter: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def rename_column_for_alter: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped def add_index_for_alter: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> ::String def remove_index_for_alter: (untyped table_name, ?::Hash[untyped, untyped] options) -> ::String def supports_rename_index?: () -> untyped def configure_connection: () -> untyped def column_definitions: (untyped table_name) -> untyped def create_table_info: (untyped table_name) -> untyped def arel_visitor: () -> untyped def build_statement_pool: () -> untyped def mismatched_foreign_key: (untyped message, binds: untyped binds, sql: untyped sql) -> untyped def version_string: (untyped full_version_string) -> untyped class MysqlString < ActiveModel::Type::String # :nodoc: def serialize: (untyped value) -> untyped def cast_value: (untyped value) -> untyped end end end end module ActiveRecord module ConnectionAdapters # :nodoc: module QueryCache def self.included: (untyped base) -> untyped def self.dirties_query_cache: (untyped base, *untyped method_names) -> untyped module ConnectionPoolConfiguration def initialize: () -> untyped def enable_query_cache!: () -> untyped def disable_query_cache!: () -> untyped def query_cache_enabled: () -> untyped end attr_reader query_cache: untyped attr_reader query_cache_enabled: untyped def initialize: () -> untyped # Enable the query cache within the block. def cache: () { () -> untyped } -> untyped def enable_query_cache!: () -> untyped def disable_query_cache!: () -> untyped # Disable the query cache within the block. def uncached: () { () -> untyped } -> untyped # 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. def clear_query_cache: () -> untyped def select_all: (untyped arel, ?untyped? name, ?untyped binds, ?preparable: untyped? preparable) -> untyped def cache_sql: (untyped sql, untyped name, untyped binds) { () -> untyped } -> untyped # Database adapters can override this method to # provide custom cache information. def cache_notification_info: (untyped sql, untyped name, untyped binds) -> { sql: untyped, binds: untyped, type_casted_binds: untyped, name: untyped, connection_id: untyped, connection: untyped, cached: ::TrueClass } # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such # queries should not be cached. def locked?: (untyped arel) -> untyped def configure_query_cache!: () -> untyped end end end module ActiveRecord module ConnectionAdapters # :nodoc: module Quoting # Quotes the column value to help prevent # {SQL injection attacks}[https://en.wikipedia.org/wiki/SQL_injection]. def quote: (untyped value) -> untyped # 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. def type_cast: (untyped value, ?untyped? column) -> untyped def type_cast_from_column: (untyped column, untyped value) -> untyped def lookup_cast_type_from_column: (untyped column) -> untyped # Quotes a string, escaping any ' (single quote) and \ (backslash) # characters. def quote_string: (untyped s) -> untyped # Quotes the column name. Defaults to no quoting. def quote_column_name: (untyped column_name) -> untyped # Quotes the table name. Defaults to column name quoting. def quote_table_name: (untyped table_name) -> untyped # 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). def quote_table_name_for_assignment: (untyped table, untyped attr) -> untyped def quote_default_expression: (untyped value, untyped column) -> untyped def quoted_true: () -> "TRUE" def unquoted_true: () -> ::TrueClass def quoted_false: () -> "FALSE" def unquoted_false: () -> ::FalseClass # Quote date/time values for use in SQL input. Includes microseconds # if the value is a Time responding to usec. def quoted_date: (untyped value) -> untyped def quoted_time: (untyped value) -> untyped def quoted_binary: (untyped value) -> ::String def sanitize_as_sql_comment: (untyped value) -> untyped def column_name_matcher: () -> untyped def column_name_with_order_matcher: () -> untyped # Regexp for column names (with or without a table name prefix). # Matches the following: # # "#{table_name}.#{column_name}" # "#{column_name}" COLUMN_NAME: untyped # Regexp for column names with order (with or without a table name prefix, # with or without various order modifiers). Matches the following: # # "#{table_name}.#{column_name}" # "#{table_name}.#{column_name} #{direction}" # "#{table_name}.#{column_name} #{direction} NULLS FIRST" # "#{table_name}.#{column_name} NULLS LAST" # "#{column_name}" # "#{column_name} #{direction}" # "#{column_name} #{direction} NULLS FIRST" # "#{column_name} NULLS LAST" COLUMN_NAME_WITH_ORDER: untyped def type_casted_binds: (untyped binds) -> untyped def lookup_cast_type: (untyped sql_type) -> untyped def id_value_for_database: (untyped value) -> untyped def _quote: (untyped value) -> untyped def _type_cast: (untyped value) -> untyped end end end module ActiveRecord module ConnectionAdapters module Savepoints def current_savepoint_name: () -> untyped def create_savepoint: (?untyped name) -> untyped def exec_rollback_to_savepoint: (?untyped name) -> untyped def release_savepoint: (?untyped name) -> untyped end end end module ActiveRecord module ConnectionAdapters class AbstractAdapter class SchemaCreation # :nodoc: def initialize: (untyped conn) -> untyped def accept: (untyped o) -> untyped def visit_AlterTable: (untyped o) -> untyped def visit_ColumnDefinition: (untyped o) -> untyped def visit_AddColumnDefinition: (untyped o) -> untyped def visit_TableDefinition: (untyped o) -> untyped def visit_PrimaryKeyDefinition: (untyped o) -> ::String def visit_ForeignKeyDefinition: (untyped o) -> untyped def visit_AddForeignKey: (untyped o) -> ::String def visit_DropForeignKey: (untyped name) -> ::String def table_options: (untyped o) -> untyped def add_table_options!: (untyped create_sql, untyped options) -> untyped def column_options: (untyped o) -> untyped def add_column_options!: (untyped sql, untyped options) -> untyped def to_sql: (untyped sql) -> untyped # Returns any SQL string to go between CREATE and TABLE. May be nil. def table_modifier_in_create: (untyped o) -> untyped def foreign_key_in_create: (untyped from_table, untyped to_table, untyped options) -> untyped def action_sql: (untyped action, untyped dependency) -> untyped end end SchemaCreation: untyped end end module ActiveRecord module ConnectionAdapters class IndexDefinition # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader table: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader name: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader unique: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader columns: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader lengths: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader orders: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader opclasses: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader where: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader type: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader using: untyped # nodoc: # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements#indexes # :nodoc: attr_reader comment: untyped def initialize: (untyped table, untyped name, ?bool unique, ?untyped columns, ?comment: untyped? comment, ?using: untyped? using, ?type: untyped? `type`, ?where: untyped? where, ?opclasses: ::Hash[untyped, untyped] opclasses, ?orders: ::Hash[untyped, untyped] orders, ?lengths: ::Hash[untyped, untyped] lengths) -> untyped def concise_options: (untyped options) -> untyped end class ColumnDefinition < ::Struct[untyped] attr_accessor name(): untyped attr_accessor type(): untyped attr_accessor options(): untyped attr_accessor sql_type(): untyped # Abstract representation of a column definition. Instances of this type # are typically created by methods in TableDefinition, and added to the # +columns+ attribute of said TableDefinition object, in order to be used # for generating a number of table creation or table changing SQL statements. # :nodoc: def primary_key?: () -> untyped end class AddColumnDefinition < ::Struct[untyped] attr_accessor column(): untyped end class ChangeColumnDefinition < ::Struct[untyped] attr_accessor column(): untyped attr_accessor name(): untyped end class PrimaryKeyDefinition < ::Struct[untyped] attr_accessor name(): untyped end class ForeignKeyDefinition < ::Struct[untyped] attr_accessor from_table(): untyped attr_accessor to_table(): untyped attr_accessor options(): untyped # nodoc: def name: () -> untyped def column: () -> untyped def primary_key: () -> untyped def on_delete: () -> untyped def on_update: () -> untyped def custom_primary_key?: () -> untyped def validate?: () -> untyped def export_name_on_schema_dump?: () -> untyped def defined_for?: (?to_table: untyped? to_table, **untyped options) -> untyped def default_primary_key: () -> "id" end class ReferenceDefinition # :nodoc: def initialize: (untyped name, ?type: ::Symbol `type`, ?foreign_key: bool foreign_key, ?index: bool index, ?polymorphic: bool polymorphic, **untyped options) -> untyped def add_to: (untyped table) -> untyped attr_reader name: untyped attr_reader polymorphic: untyped attr_reader index: untyped attr_reader foreign_key: untyped attr_reader type: untyped attr_reader options: untyped def as_options: (untyped value) -> untyped def polymorphic_options: () -> untyped def index_options: () -> untyped def foreign_key_options: () -> untyped def columns: () -> untyped def column_name: () -> ::String def column_names: () -> untyped def foreign_table_name: () -> untyped end module ColumnMethods extend ActiveSupport::Concern # Appends a primary key definition to the table definition. # Can be called multiple times, but this is probably not a good idea. def primary_key: (untyped name, ?::Symbol `type`, **untyped options) -> untyped module ClassMethods def define_column_methods: (*untyped column_types) -> untyped end end # 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}[rdoc-ref:SchemaStatements#create_table] # is actually of this type: # # class SomeMigration < ActiveRecord::Migration[5.0] # def up # create_table :foo do |t| # puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition" # end # end # # def down # ... # end # end # class TableDefinition include ColumnMethods extend ::ActiveRecord::ConnectionAdapters::ColumnMethods::ClassMethods attr_reader name: untyped attr_reader temporary: untyped attr_reader if_not_exists: untyped attr_reader options: untyped attr_reader as: untyped attr_reader comment: untyped attr_reader indexes: untyped attr_reader foreign_keys: untyped def initialize: (untyped conn, untyped name, ?comment: untyped? comment, ?as: untyped? as, ?options: untyped? options, ?if_not_exists: bool if_not_exists, ?temporary: bool temporary) -> untyped def primary_keys: (?untyped? name) -> untyped # Returns an array of ColumnDefinition objects for the columns of the table. def columns: () -> untyped # Returns a ColumnDefinition for the column with name +name+. def []: (untyped name) -> untyped # Instantiates a new column for the table. # See {connection.add_column}[rdoc-ref:ConnectionAdapters::SchemaStatements#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}[rdoc-ref:ConnectionAdapters::SchemaStatements#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 def column: (untyped name, untyped `type`, **untyped options) -> untyped # remove the column +name+ from the table. # remove_column(:account_id) def remove_column: (untyped name) -> untyped # 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') def index: (untyped column_name, ?::Hash[untyped, untyped] options) -> untyped def foreign_key: (untyped table_name, **untyped options) -> untyped # Appends :datetime columns :created_at and # :updated_at to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps] # # t.timestamps null: false def timestamps: (**untyped options) -> untyped # 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}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use. def references: (*untyped args, **untyped options) -> untyped def new_column_definition: (untyped name, untyped `type`, **untyped options) -> untyped def create_column_definition: (untyped name, untyped `type`, untyped options) -> ColumnDefinition def aliased_types: (untyped name, untyped fallback) -> untyped def integer_like_primary_key?: (untyped `type`, untyped options) -> untyped def integer_like_primary_key_type: (untyped `type`, untyped options) -> untyped end class AlterTable # :nodoc: attr_reader adds: untyped attr_reader foreign_key_adds: untyped attr_reader foreign_key_drops: untyped def initialize: (untyped td) -> untyped def name: () -> untyped def add_foreign_key: (untyped to_table, untyped options) -> untyped def drop_foreign_key: (untyped name) -> untyped def add_column: (untyped name, untyped `type`, **untyped options) -> untyped end # Represents an SQL table in an abstract way for updating a table. # Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#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.rename # t.references # t.belongs_to # 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.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_timestamps # end # class Table include ColumnMethods extend ::ActiveRecord::ConnectionAdapters::ColumnMethods::ClassMethods attr_reader name: untyped def initialize: (untyped table_name, untyped base) -> untyped # Adds a new column to the named table. # # t.column(:name, :string) # # See TableDefinition#column for details of the options you can use. def column: (untyped column_name, untyped `type`, **untyped options) -> untyped # Checks to see if a column exists. # # t.string(:name) unless t.column_exists?(:name, :string) # # See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?] def column_exists?: (untyped column_name, ?untyped? `type`, **untyped options) -> untyped # 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}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use. def index: (untyped column_name, ?::Hash[untyped, untyped] options) -> untyped # Checks to see if an index exists. # # unless t.index_exists?(:branch_id) # t.index(:branch_id) # end # # See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?] def index_exists?: (untyped column_name, ?::Hash[untyped, untyped] options) -> untyped # Renames the given index on the table. # # t.rename_index(:user_id, :account_id) # # See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index] def rename_index: (untyped index_name, untyped new_index_name) -> untyped # Adds timestamps (+created_at+ and +updated_at+) columns to the table. # # t.timestamps(null: false) # # See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps] def timestamps: (**untyped options) -> untyped # 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. def change: (untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped # 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}[rdoc-ref:SchemaStatements#change_column_default] def change_default: (untyped column_name, untyped default_or_changes) -> untyped # Removes the column(s) from the table definition. # # t.remove(:qualification) # t.remove(:qualification, :experience) # # See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns] def remove: (*untyped column_names) -> untyped # 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) # # See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index] def remove_index: (?::Hash[untyped, untyped] options) -> untyped # Removes the timestamp columns (+created_at+ and +updated_at+) from the table. # # t.remove_timestamps # # See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps] def remove_timestamps: (**untyped options) -> untyped # Renames a column. # # t.rename(:description, :name) # # See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column] def rename: (untyped column_name, untyped new_column_name) -> untyped # Adds a reference. # # t.references(:user) # t.belongs_to(:supplier, foreign_key: true) # # See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use. def references: (*untyped args, **untyped options) -> untyped # Removes a reference. Optionally removes a +type+ column. # # t.remove_references(:user) # t.remove_belongs_to(:supplier, polymorphic: true) # # See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference] def remove_references: (*untyped args, **untyped options) -> untyped # 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}[rdoc-ref:SchemaStatements#add_foreign_key] def foreign_key: (*untyped args, **untyped options) -> untyped # 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}[rdoc-ref:SchemaStatements#remove_foreign_key] def remove_foreign_key: (*untyped args, **untyped options) -> untyped # Checks to see if a foreign key exists. # # t.foreign_key(:authors) unless t.foreign_key_exists?(:authors) # # See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?] def foreign_key_exists?: (*untyped args, **untyped options) -> untyped end end end module ActiveRecord module ConnectionAdapters class SchemaDumper < ActiveRecord::SchemaDumper # :nodoc: # :nodoc: def self.create: (untyped connection, untyped options) -> untyped def column_spec: (untyped column) -> ::Array[untyped] def column_spec_for_primary_key: (untyped column) -> (::Hash[untyped, untyped] | untyped) def prepare_column_options: (untyped column) -> untyped def default_primary_key?: (untyped column) -> untyped def explicit_primary_key_default?: (untyped column) -> ::FalseClass def schema_type_with_virtual: (untyped column) -> untyped def schema_type: (untyped column) -> untyped def schema_limit: (untyped column) -> untyped def schema_precision: (untyped column) -> untyped def schema_scale: (untyped column) -> untyped def schema_default: (untyped column) -> (nil | untyped) def schema_expression: (untyped column) -> untyped def schema_collation: (untyped column) -> untyped end end end module ActiveRecord module ConnectionAdapters # :nodoc: module SchemaStatements include ActiveRecord::Migration::JoinTable # 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. def native_database_types: () -> ::Hash[untyped, untyped] def table_options: (untyped table_name) -> nil # Returns the table comment that's stored in database metadata. def table_comment: (untyped table_name) -> nil # Truncates a table alias according to the limits of the current adapter. def table_alias_for: (untyped table_name) -> untyped # Returns the relation names useable to back Active Record models. # For most adapters this means all #tables and #views. def data_sources: () -> untyped # Checks to see if the data source +name+ exists on the database. # # data_source_exists?(:ebooks) # def data_source_exists?: (untyped name) -> untyped # Returns an array of table names defined in the database. def tables: () -> untyped # Checks to see if the table +table_name+ exists on the database. # # table_exists?(:developers) # def table_exists?: (untyped table_name) -> untyped # Returns an array of view names defined in the database. def views: () -> untyped # Checks to see if the view +view_name+ exists on the database. # # view_exists?(:ebooks) # def view_exists?: (untyped view_name) -> untyped # Returns an array of indexes for the given table. def indexes: (untyped table_name) -> untyped # 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") # def index_exists?: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> untyped # Returns an array of +Column+ objects for the table specified by +table_name+. def columns: (untyped table_name) -> untyped # 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 # 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) # def column_exists?: (untyped table_name, untyped column_name, ?untyped? `type`, **untyped options) -> untyped # Returns just a table's primary key def primary_key: (untyped table_name) -> untyped # 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}[rdoc-ref:Associations::ClassMethods#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=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#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 order ( # 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. def create_table: (untyped table_name, **untyped options) { (untyped) -> untyped } -> untyped # 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 # def create_join_table: (untyped table_1, untyped table_2, ?column_options: ::Hash[untyped, untyped] column_options, **untyped options) { (untyped) -> untyped } -> untyped # 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. def drop_join_table: (untyped table_1, untyped table_2, **untyped options) -> untyped # 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 # # ====== 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. def change_table: (untyped table_name, **untyped options) { (untyped) -> untyped } -> untyped # Renames a table. # # rename_table('octopuses', 'octopi') # def rename_table: (untyped table_name, untyped new_name) -> untyped # 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. def drop_table: (untyped table_name, **untyped options) -> untyped # Add a new +type+ column named +column_name+ to +table_name+. # # 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, :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): # * :limit - # Requests a maximum column length. This is the number of characters for a :string column # and number of bytes for :text, :binary, and :integer columns. # This option is ignored by some backends. # * :default - # The column's default value. Use +nil+ for +NULL+. # * :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. # # 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). # * DB2: :precision [1..63], :scale [0..62]. # Default unknown. # * 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 def add_column: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> untyped # Removes the given columns from the table definition. # # remove_columns(:suppliers, :qualification, :experience) # def remove_columns: (untyped table_name, *untyped column_names) -> untyped # 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. # Indexes on the column are automatically removed. def remove_column: (untyped table_name, untyped column_name, ?untyped? `type`, **untyped options) -> untyped # 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) # def change_column: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped # 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") # def change_column_default: (untyped table_name, untyped column_name, untyped default_or_changes) -> untyped # 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. def change_column_null: (untyped table_name, untyped column_name, untyped null, ?untyped? default) -> untyped # Renames a column. # # rename_column(:suppliers, :description, :name) # def rename_column: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped # 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 suppliers_name_index ON suppliers(name) # # ====== Creating a unique index # # add_index(:accounts, [:branch_id, :party_id], unique: true) # # generates: # # CREATE UNIQUE INDEX accounts_branch_id_party_id_index 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: SQLite doesn't support index length. # # ====== Creating an index with a sort order (desc or asc, asc is the default) # # add_index(:accounts, [:branch_id, :party_id, :surname], 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 3.8.0+. # # ====== 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}[rdoc-ref:Migration]. def add_index: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> untyped # 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 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}[rdoc-ref:Migration]. def remove_index: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped # 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' # def rename_index: (untyped table_name, untyped old_name, untyped new_name) -> (nil | untyped) def index_name: (untyped table_name, untyped options) -> untyped # Verifies the existence of an index with a given name. def index_name_exists?: (untyped table_name, untyped index_name) -> untyped # 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. # [: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}) # def add_reference: (untyped table_name, untyped ref_name, **untyped options) -> untyped # 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) # def remove_reference: (untyped table_name, untyped ref_name, ?polymorphic: bool polymorphic, ?foreign_key: bool foreign_key, **untyped options) -> untyped # Returns an array of foreign keys for the given table. # The foreign keys are represented as ForeignKeyDefinition objects. def foreign_keys: (untyped table_name) -> untyped # 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+ 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 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_. # [: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+ # [:validate] # (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+. def add_foreign_key: (untyped from_table, untyped to_table, **untyped options) -> (nil | untyped) # 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 # # 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. def remove_foreign_key: (untyped from_table, ?untyped? to_table, **untyped options) -> (nil | untyped) # 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") # def foreign_key_exists?: (untyped from_table, ?untyped? to_table, **untyped options) -> untyped def foreign_key_column_for: (untyped table_name) -> ::String def foreign_key_options: (untyped from_table, untyped to_table, untyped options) -> untyped def dump_schema_information: () -> untyped def internal_string_options_for_primary_key: () -> { primary_key: ::TrueClass } def assume_migrated_upto_version: (untyped version, ?untyped? migrations_paths) -> untyped def type_to_sql: (untyped `type`, ?scale: untyped? scale, ?precision: untyped? precision, ?limit: untyped? limit) -> untyped def columns_for_distinct: (untyped columns, untyped orders) -> untyped # 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) # def add_timestamps: (untyped table_name, **untyped options) -> untyped # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition. # # remove_timestamps(:suppliers) # def remove_timestamps: (untyped table_name, **untyped options) -> untyped def update_table_definition: (untyped table_name, untyped base) -> Table def add_index_options: (untyped table_name, untyped column_name, ?comment: untyped? comment, **untyped options) -> ::Array[untyped] def options_include_default?: (untyped options) -> untyped # 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") def change_table_comment: (untyped table_name, untyped comment_or_changes) -> untyped # 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") def change_column_comment: (untyped table_name, untyped column_name, untyped comment_or_changes) -> untyped def create_schema_dumper: (untyped options) -> untyped def column_options_keys: () -> ::Array[:limit | :precision | :scale | :default | :null | :collation | :comment] def add_index_sort_order: (untyped quoted_columns, **untyped options) -> untyped def options_for_index_columns: (untyped options) -> untyped # Overridden by the MySQL adapter for supporting index lengths and by # the PostgreSQL adapter for supporting operator classes. def add_options_for_index_columns: (untyped quoted_columns, **untyped options) -> untyped def quoted_columns_for_index: (untyped column_names, **untyped options) -> (::Array[untyped] | untyped) def index_name_for_remove: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped def rename_table_indexes: (untyped table_name, untyped new_name) -> untyped def rename_column_indexes: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped def schema_creation: () -> untyped def create_table_definition: (*untyped args, **untyped options) -> TableDefinition def create_alter_table: (untyped name) -> AlterTable def fetch_type_metadata: (untyped sql_type) -> SqlTypeMetadata def index_column_names: (untyped column_names) -> untyped def index_name_options: (untyped column_names) -> { column: untyped } def strip_table_name_prefix_and_suffix: (untyped table_name) -> untyped def foreign_key_name: (untyped table_name, untyped options) -> untyped def foreign_key_for: (untyped from_table, **untyped options) -> (nil | untyped) def foreign_key_for!: (untyped from_table, ?to_table: untyped? to_table, **untyped options) -> untyped def extract_foreign_key_action: (untyped specifier) -> untyped def validate_index_length!: (untyped table_name, untyped new_name, ?bool internal) -> untyped def extract_new_default_value: (untyped default_or_changes) -> untyped def can_remove_index_by_name?: (untyped options) -> untyped def bulk_change_table: (untyped table_name, untyped operations) -> untyped def add_column_for_alter: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> untyped def remove_column_for_alter: (untyped table_name, untyped column_name, ?untyped? `type`, **untyped options) -> ::String def remove_columns_for_alter: (untyped table_name, *untyped column_names, **untyped options) -> untyped def add_timestamps_for_alter: (untyped table_name, **untyped options) -> ::Array[untyped] def remove_timestamps_for_alter: (untyped table_name, **untyped options) -> untyped def insert_versions_sql: (untyped versions) -> untyped def data_source_sql: (?untyped? name, ?type: untyped? `type`) -> untyped def quoted_scope: (?untyped? name, ?type: untyped? `type`) -> untyped end end end module ActiveRecord module ConnectionAdapters class TransactionState def initialize: (?untyped? state) -> untyped def add_child: (untyped state) -> untyped def finalized?: () -> untyped def committed?: () -> untyped def fully_committed?: () -> untyped def rolledback?: () -> untyped def fully_rolledback?: () -> untyped def fully_completed?: () -> untyped def completed?: () -> untyped def rollback!: () -> untyped def full_rollback!: () -> untyped def commit!: () -> untyped def full_commit!: () -> untyped def nullify!: () -> untyped end class NullTransaction # nodoc: def initialize: () -> nil def state: () -> nil def closed?: () -> ::TrueClass def open?: () -> ::FalseClass def joinable?: () -> ::FalseClass def add_record: (untyped record) -> nil end class Transaction # nodoc: attr_reader connection: untyped # nodoc: attr_reader state: untyped # nodoc: attr_reader records: untyped # nodoc: attr_reader savepoint_name: untyped # nodoc: attr_reader isolation_level: untyped def initialize: (untyped connection, untyped options, ?run_commit_callbacks: bool run_commit_callbacks) -> untyped def add_record: (untyped record) -> untyped def materialize!: () -> untyped def materialized?: () -> untyped def rollback_records: () -> untyped def before_commit_records: () -> untyped def commit_records: () -> untyped def full_rollback?: () -> ::TrueClass def joinable?: () -> untyped def closed?: () -> ::FalseClass def open?: () -> untyped end class SavepointTransaction < Transaction def initialize: (untyped connection, untyped savepoint_name, untyped parent_transaction, *untyped args, **untyped options) -> untyped def materialize!: () -> untyped def rollback: () -> untyped def commit: () -> untyped def full_rollback?: () -> ::FalseClass end class RealTransaction < Transaction def materialize!: () -> untyped def rollback: () -> untyped def commit: () -> untyped end class TransactionManager # nodoc: def initialize: (untyped connection) -> untyped def begin_transaction: (?::Hash[untyped, untyped] options) -> untyped def disable_lazy_transactions!: () -> untyped def enable_lazy_transactions!: () -> untyped def lazy_transactions_enabled?: () -> untyped def materialize_transactions: () -> (nil | untyped) def commit_transaction: () -> untyped def rollback_transaction: (?untyped? transaction) -> untyped def within_new_transaction: (?::Hash[untyped, untyped] options) { () -> untyped } -> untyped def open_transactions: () -> untyped def current_transaction: () -> untyped NULL_TRANSACTION: untyped # Deallocate invalidated prepared statements outside of the transaction def after_failure_actions: (untyped transaction, untyped error) -> (nil | untyped) end end end module ActiveRecord # :stopdoc: module ConnectionAdapters # An abstract definition of a column in a table. class Column attr_reader name: untyped attr_reader default: untyped attr_reader sql_type_metadata: untyped attr_reader null: untyped attr_reader default_function: untyped attr_reader collation: untyped attr_reader comment: untyped # Instantiates a new column in the table. # # +name+ is the column's name, such as supplier_id in supplier_id bigint. # +default+ is the type-casted default value, such as +new+ in sales_stage varchar(20) default 'new'. # +sql_type_metadata+ is various information about the type of the column # +null+ determines if this column allows +NULL+ values. def initialize: (untyped name, untyped default, ?untyped? sql_type_metadata, ?bool null, ?untyped? default_function, ?comment: untyped? comment, ?collation: untyped? collation) -> untyped def has_default?: () -> untyped def bigint?: () -> untyped # Returns the human name of the column name. # # ===== Examples # Column.new('sales_stage', ...).human_name # => 'Sales stage' def human_name: () -> untyped def init_with: (untyped coder) -> untyped def encode_with: (untyped coder) -> untyped def ==: (untyped other) -> untyped def hash: () -> untyped end class NullColumn < Column def initialize: (untyped name) -> untyped end end end module ActiveRecord module ConnectionAdapters class ConnectionSpecification # nodoc: attr_reader name: untyped # nodoc: attr_reader config: untyped # nodoc: attr_reader adapter_method: untyped def initialize: (untyped name, untyped config, untyped adapter_method) -> untyped def initialize_dup: (untyped original) -> untyped def to_hash: () -> untyped class ConnectionUrlResolver # Expands a connection string into a hash. # :nodoc: # == Example # # url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000" # ConnectionUrlResolver.new(url).to_hash # # => { # "adapter" => "postgresql", # "host" => "localhost", # "port" => 9000, # "database" => "foo_test", # "username" => "foo", # "password" => "bar", # "pool" => "5", # "timeout" => "3000" # } def initialize: (untyped url) -> untyped # Converts the given URL to a full connection hash. def to_hash: () -> untyped attr_reader uri: untyped def uri_parser: () -> untyped # Converts the query parameters of the URI into a hash. # # "localhost?pool=5&reaping_frequency=2" # # => { "pool" => "5", "reaping_frequency" => "2" } # # returns empty hash if no query present. # # "localhost" # # => {} def query_hash: () -> untyped def raw_config: () -> untyped # Returns name of the database. def database_from_path: () -> untyped end class Resolver # # Builds a ConnectionSpecification from user input. # :nodoc: attr_reader configurations: untyped # Accepts a list of db config objects. def initialize: (untyped configurations) -> untyped # Returns a hash with database connection information. # # == Examples # # Full hash Configuration. # # configurations = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } } # Resolver.new(configurations).resolve(:production) # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3"} # # Initialized with URL configuration strings. # # configurations = { "production" => "postgresql://localhost/foo" } # Resolver.new(configurations).resolve(:production) # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" } # def resolve: (untyped config_or_env, ?untyped? pool_name) -> untyped # Returns an instance of ConnectionSpecification for a given adapter. # Accepts a hash one layer deep that contains all connection information. # # == Example # # config = { "production" => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } } # spec = Resolver.new(config).spec(:production) # spec.adapter_method # # => "sqlite3_connection" # spec.config # # => { "host" => "localhost", "database" => "foo", "adapter" => "sqlite3" } # def spec: (untyped config) -> ConnectionSpecification # Returns fully resolved connection, accepts hash, string or symbol. # Always returns a hash. # # == Examples # # Symbol representing current environment. # # Resolver.new("production" => {}).resolve_connection(:production) # # => {} # # One layer deep hash of connection values. # # Resolver.new({}).resolve_connection("adapter" => "sqlite3") # # => { "adapter" => "sqlite3" } # # Connection URL. # # Resolver.new({}).resolve_connection("postgresql://localhost/foo") # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" } # def resolve_connection: (untyped config_or_env, ?untyped? pool_name) -> untyped # Takes the environment such as +:production+ or +:development+ and a # pool name the corresponds to the name given by the connection pool # to the connection. That pool name is merged into the hash with the # name key. # # This requires that the @configurations was initialized with a key that # matches. # # configurations = #"my_db"}> # ]> # # Resolver.new(configurations).resolve_symbol_connection(:production, "primary") # # => { "database" => "my_db" } def resolve_symbol_connection: (untyped env_name, untyped pool_name) -> untyped def build_configuration_sentence: () -> untyped # Accepts a hash. Expands the "url" key that contains a # URL database connection to a full connection # hash and merges with the rest of the hash. # Connection details inside of the "url" key win any merge conflicts def resolve_hash_connection: (untyped spec) -> untyped # Takes a connection URL. # # Resolver.new({}).resolve_url_connection("postgresql://localhost/foo") # # => { "host" => "localhost", "database" => "foo", "adapter" => "postgresql" } # def resolve_url_connection: (untyped url) -> untyped end end end end module ActiveRecord module ConnectionAdapters module DetermineIfPreparableVisitor attr_accessor preparable: untyped def accept: (untyped object, untyped collector) -> untyped def visit_Arel_Nodes_In: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NotIn: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SqlLiteral: (untyped o, untyped collector) -> untyped end end end module ActiveRecord module ConnectionHandling # :nodoc: ER_BAD_DB_ERROR: ::Integer # Establishes a connection to the database that's used by all Active Record objects. def mysql2_connection: (untyped config) -> untyped end module ConnectionAdapters class Mysql2Adapter < AbstractMysqlAdapter ADAPTER_NAME: ::String include MySQL::DatabaseStatements def initialize: (untyped connection, untyped logger, untyped connection_options, untyped config) -> untyped def self.database_exists?: (untyped config) -> untyped def supports_json?: () -> untyped def supports_comments?: () -> ::TrueClass def supports_comments_in_create?: () -> ::TrueClass def supports_savepoints?: () -> ::TrueClass def supports_lazy_transactions?: () -> ::TrueClass def each_hash: (untyped result) { (untyped) -> untyped } -> untyped def error_number: (untyped exception) -> untyped def quote_string: (untyped string) -> untyped def active?: () -> untyped def reconnect!: () -> untyped # Disconnects from the database if already connected. # Otherwise, this method does nothing. def disconnect!: () -> untyped def discard!: () -> untyped def connect: () -> untyped def configure_connection: () -> untyped def full_version: () -> untyped def get_full_version: () -> untyped end end end module ActiveRecord module ConnectionAdapters module MySQL class Column < ConnectionAdapters::Column def unsigned?: () -> untyped def case_sensitive?: () -> untyped def auto_increment?: () -> untyped def virtual?: () -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL module DatabaseStatements def select_all: () -> untyped def query: (untyped sql, ?untyped? name) -> untyped READ_QUERY: untyped def write_query?: (untyped sql) -> untyped # Executes the SQL statement in the context of this connection. def execute: (untyped sql, ?untyped? name) -> untyped def exec_query: (untyped sql, ?::String name, ?untyped binds, ?prepare: bool prepare) -> untyped def exec_delete: (untyped sql, ?untyped? name, ?untyped binds) -> untyped def execute_batch: (untyped statements, ?untyped? name) -> untyped def default_insert_value: (untyped column) -> untyped def last_inserted_id: (untyped result) -> untyped def supports_set_server_option?: () -> untyped def multi_statements_enabled?: (untyped flags) -> untyped def with_multi_statements: () { () -> untyped } -> untyped def combine_multi_statements: (untyped total_sql) -> untyped def max_allowed_packet_reached?: (untyped current_packet, untyped previous_packet) -> untyped def max_allowed_packet: () -> untyped def exec_stmt_and_free: (untyped sql, untyped name, untyped binds, ?cache_stmt: bool cache_stmt) { (untyped, untyped) -> untyped } -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL class ExplainPrettyPrinter # :nodoc: # Pretty prints the result of an EXPLAIN in a way that resembles the output of the # MySQL shell: # # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ # | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ # | 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | | # | 1 | SIMPLE | posts | ALL | NULL | NULL | NULL | NULL | 1 | Using where | # +----+-------------+-------+-------+---------------+---------+---------+-------+------+-------------+ # 2 rows in set (0.00 sec) # # This is an exercise in Ruby hyperrealism :). def pp: (untyped result, untyped elapsed) -> untyped def compute_column_widths: (untyped result) -> untyped def build_separator: (untyped widths) -> untyped def build_cells: (untyped items, untyped widths) -> untyped def build_footer: (untyped nrows, untyped elapsed) -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL module Quoting # :nodoc: def quote_column_name: (untyped name) -> untyped def quote_table_name: (untyped name) -> untyped def unquoted_true: () -> 1 def unquoted_false: () -> 0 def quoted_date: (untyped value) -> untyped def quoted_binary: (untyped value) -> ::String def column_name_matcher: () -> untyped def column_name_with_order_matcher: () -> untyped COLUMN_NAME: untyped COLUMN_NAME_WITH_ORDER: untyped def _type_cast: (untyped value) -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL class SchemaCreation < AbstractAdapter::SchemaCreation def visit_DropForeignKey: (untyped name) -> ::String def visit_AddColumnDefinition: (untyped o) -> untyped def visit_ChangeColumnDefinition: (untyped o) -> untyped def add_table_options!: (untyped create_sql, untyped options) -> untyped def add_column_options!: (untyped sql, untyped options) -> untyped def add_column_position!: (untyped sql, untyped options) -> untyped def index_in_create: (untyped table_name, untyped column_name, untyped options) -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL module ColumnMethods extend ActiveSupport::Concern end class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition include ColumnMethods def new_column_definition: (untyped name, untyped `type`, **untyped options) -> untyped def aliased_types: (untyped name, untyped fallback) -> untyped def integer_like_primary_key_type: (untyped `type`, untyped options) -> untyped end class Table < ActiveRecord::ConnectionAdapters::Table include ColumnMethods end end end end module ActiveRecord module ConnectionAdapters module MySQL class SchemaDumper < ConnectionAdapters::SchemaDumper def prepare_column_options: (untyped column) -> untyped def column_spec_for_primary_key: (untyped column) -> untyped def default_primary_key?: (untyped column) -> untyped def explicit_primary_key_default?: (untyped column) -> untyped def schema_type: (untyped column) -> untyped def schema_limit: (untyped column) -> untyped def schema_precision: (untyped column) -> untyped def schema_collation: (untyped column) -> untyped def extract_expression_for_virtual_column: (untyped column) -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL module SchemaStatements # :nodoc: # Returns an array of indexes for the given table. def indexes: (untyped table_name) -> untyped def remove_column: (untyped table_name, untyped column_name, ?untyped? `type`, **untyped options) -> untyped def create_table: (untyped table_name, ?options: untyped options) -> untyped def internal_string_options_for_primary_key: () -> untyped def update_table_definition: (untyped table_name, untyped base) -> untyped def create_schema_dumper: (untyped options) -> untyped # Maps logical Rails types to MySQL-specific data types. def type_to_sql: (untyped `type`, ?unsigned: untyped? unsigned, ?size: untyped size, ?scale: untyped? scale, ?precision: untyped? precision, ?limit: untyped? limit) -> untyped def table_alias_length: () -> 256 CHARSETS_OF_4BYTES_MAXLEN: ::Array[untyped] def row_format_dynamic_by_default?: () -> untyped def default_row_format: () -> (nil | untyped) def schema_creation: () -> MySQL::SchemaCreation def create_table_definition: (*untyped args, **untyped options) -> MySQL::TableDefinition def new_column_from_field: (untyped table_name, untyped field) -> MySQL::Column def fetch_type_metadata: (untyped sql_type, ?::String extra) -> MySQL::TypeMetadata def extract_foreign_key_action: (untyped specifier) -> untyped def add_index_length: (untyped quoted_columns, **untyped options) -> untyped def add_options_for_index_columns: (untyped quoted_columns, **untyped options) -> untyped def data_source_sql: (?untyped? name, ?type: untyped? `type`) -> untyped def quoted_scope: (?untyped? name, ?type: untyped? `type`) -> untyped def extract_schema_qualified_name: (untyped string) -> ::Array[untyped] def type_with_size_to_sql: (untyped `type`, untyped size) -> untyped def limit_to_size: (untyped limit, untyped `type`) -> untyped def integer_to_sql: (untyped limit) -> untyped end end end end module ActiveRecord module ConnectionAdapters module MySQL # Note: It inherits unnamed class, but omitted class TypeMetadata attr_reader extra: untyped def initialize: (untyped type_metadata, ?extra: ::String extra) -> untyped def ==: (untyped other) -> untyped def hash: () -> untyped end end end end class ::PG::Connection end module ActiveRecord module ConnectionHandling # :nodoc: # Establishes a connection to the database that's used by all Active Record objects def postgresql_connection: (untyped config) -> untyped end module ConnectionAdapters # The PostgreSQL adapter works with the native C (https://bitbucket.org/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 user name. # * :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 # call on the connection. # * :min_messages - An optional client min messages that is used in a # SET client_min_messages TO 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 # https://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 https://www.postgresql.org/docs/current/static/libpq-envars.html . class PostgreSQLAdapter < AbstractAdapter ADAPTER_NAME: ::String NATIVE_DATABASE_TYPES: ::Hash[untyped, untyped] OID: untyped include PostgreSQL::Quoting include PostgreSQL::ReferentialIntegrity include PostgreSQL::SchemaStatements include PostgreSQL::DatabaseStatements def supports_bulk_alter?: () -> ::TrueClass def supports_index_sort_order?: () -> ::TrueClass def supports_partitioned_indexes?: () -> untyped def supports_partial_index?: () -> ::TrueClass def supports_expression_index?: () -> ::TrueClass def supports_transaction_isolation?: () -> ::TrueClass def supports_foreign_keys?: () -> ::TrueClass def supports_validate_constraints?: () -> ::TrueClass def supports_views?: () -> ::TrueClass def supports_datetime_with_precision?: () -> ::TrueClass def supports_json?: () -> ::TrueClass def supports_comments?: () -> ::TrueClass def supports_savepoints?: () -> ::TrueClass def supports_insert_returning?: () -> ::TrueClass def supports_insert_on_conflict?: () -> untyped def index_algorithms: () -> { concurrently: "CONCURRENTLY" } class StatementPool < ConnectionAdapters::StatementPool # :nodoc: def initialize: (untyped connection, untyped max) -> untyped def next_key: () -> ::String def []=: (untyped sql, untyped key) -> untyped def dealloc: (untyped key) -> untyped def connection_active?: () -> untyped end # Initializes and connects a PostgreSQL adapter. def initialize: (untyped connection, untyped logger, untyped connection_parameters, untyped config) -> untyped def self.database_exists?: (untyped config) -> untyped # Is this connection alive and ready for queries? def active?: () -> untyped # Close then reopen the connection. def reconnect!: () -> untyped def reset!: () -> untyped # Disconnects from the database if already connected. Otherwise, this # method does nothing. def disconnect!: () -> untyped def discard!: () -> untyped def native_database_types: () -> untyped def set_standard_conforming_strings: () -> untyped def supports_ddl_transactions?: () -> ::TrueClass def supports_advisory_locks?: () -> ::TrueClass def supports_explain?: () -> ::TrueClass def supports_extensions?: () -> ::TrueClass def supports_ranges?: () -> ::TrueClass def supports_materialized_views?: () -> ::TrueClass def supports_foreign_tables?: () -> ::TrueClass def supports_pgcrypto_uuid?: () -> untyped def supports_optimizer_hints?: () -> untyped def supports_common_table_expressions?: () -> ::TrueClass def supports_lazy_transactions?: () -> ::TrueClass def get_advisory_lock: (untyped lock_id) -> untyped def release_advisory_lock: (untyped lock_id) -> untyped def enable_extension: (untyped name) -> untyped def disable_extension: (untyped name) -> untyped def extension_available?: (untyped name) -> untyped def extension_enabled?: (untyped name) -> untyped def extensions: () -> untyped # Returns the configured supported identifier length supported by PostgreSQL def max_identifier_length: () -> untyped # Set the authorized user for this session def session_auth=: (untyped user) -> untyped def use_insert_returning?: () -> untyped def column_name_for_operation: (untyped operation, untyped node) -> untyped OPERATION_ALIASES: ::Hash[untyped, untyped] def get_database_version: () -> untyped def default_index_type?: (untyped index) -> untyped def build_insert_sql: (untyped insert) -> untyped def check_version: () -> untyped # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html VALUE_LIMIT_VIOLATION: ::String NUMERIC_VALUE_OUT_OF_RANGE: ::String NOT_NULL_VIOLATION: ::String FOREIGN_KEY_VIOLATION: ::String UNIQUE_VIOLATION: ::String SERIALIZATION_FAILURE: ::String DEADLOCK_DETECTED: ::String LOCK_NOT_AVAILABLE: ::String QUERY_CANCELED: ::String def translate_exception: (untyped exception, binds: untyped binds, sql: untyped sql, message: untyped message) -> untyped def get_oid_type: (untyped oid, untyped fmod, untyped column_name, ?::String sql_type) -> untyped def initialize_type_map: (?untyped m) -> untyped # Extracts the value from a PostgreSQL column default definition. def extract_value_from_default: (untyped default) -> untyped def extract_default_function: (untyped default_value, untyped default) -> untyped def has_default_function?: (untyped default_value, untyped default) -> untyped def load_additional_types: (?untyped? oids) -> untyped FEATURE_NOT_SUPPORTED: ::String def execute_and_clear: (untyped sql, untyped name, untyped binds, ?prepare: bool prepare) { (untyped) -> untyped } -> untyped def exec_no_cache: (untyped sql, untyped name, untyped binds) -> untyped def exec_cache: (untyped sql, untyped name, untyped binds) -> untyped # Annoyingly, the code for prepared statements whose return value may # have changed is FEATURE_NOT_SUPPORTED. # # This covers various different error types so we need to do additional # work to classify the exception definitively as a # ActiveRecord::PreparedStatementCacheExpired # # Check here for more details: # https://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573 CACHED_PLAN_HEURISTIC: ::String def is_cached_plan_failure?: (untyped e) -> untyped def in_transaction?: () -> untyped # Returns the statement identifier for the client side cache # of statements def sql_key: (untyped sql) -> ::String # Prepare the statement if it hasn't been prepared, return # the statement key. def prepare_statement: (untyped sql, untyped binds) -> untyped # Connects to a PostgreSQL server and sets up the adapter depending on the # connected server's characteristics. def connect: () -> untyped # Configures the encoding, verbosity, schema search path, and time zone of the connection. # This is called by #connect and should not be called manually. def configure_connection: () -> untyped # Returns the list of a table's column names, data types, and default values. # # The underlying query is roughly: # SELECT column.name, column.type, default.value, column.comment # FROM column LEFT JOIN default # ON column.table_id = default.table_id # AND column.num = default.column_num # WHERE column.table_id = get_table_id('table_name') # AND column.num > 0 # AND NOT column.is_dropped # ORDER BY column.num # # If the table name is not prefixed with a schema, the database will # take the first match from the schema search path. # # Query implementation notes: # - format_type includes the column size constraint, e.g. varchar(50) # - ::regclass is a function that gives the id for a table name def column_definitions: (untyped table_name) -> untyped def extract_table_ref_from_insert_sql: (untyped sql) -> untyped def arel_visitor: () -> Arel::Visitors::PostgreSQL def build_statement_pool: () -> StatementPool def can_perform_case_insensitive_comparison_for?: (untyped column) -> untyped def add_pg_encoders: () -> untyped def update_typemap_for_default_timezone: () -> untyped def add_pg_decoders: () -> untyped def construct_coder: (untyped row, untyped coder_class) -> (nil | untyped) end end end module ActiveRecord module ConnectionAdapters module PostgreSQL class Column < ConnectionAdapters::Column def initialize: (?serial: untyped? serial) -> untyped def serial?: () -> untyped def array: () -> untyped def sql_type: () -> untyped end end PostgreSQLColumn: untyped end end module ActiveRecord module ConnectionAdapters module PostgreSQL module DatabaseStatements def explain: (untyped arel, ?untyped binds) -> untyped MONEY_COLUMN_TYPE_OID: ::Integer BYTEA_COLUMN_TYPE_OID: ::Integer def result_as_array: (untyped res) -> untyped def query: (untyped sql, ?untyped? name) -> untyped READ_QUERY: untyped def write_query?: (untyped sql) -> untyped # 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. def execute: (untyped sql, ?untyped? name) -> untyped def exec_query: (untyped sql, ?::String name, ?untyped binds, ?prepare: bool prepare) -> untyped def exec_delete: (untyped sql, ?untyped? name, ?untyped binds) -> untyped def sql_for_insert: (untyped sql, untyped pk, untyped binds) -> untyped def exec_insert: (untyped sql, ?untyped? name, ?untyped binds, ?untyped? pk, ?untyped? sequence_name) -> untyped # Begins a transaction. def begin_db_transaction: () -> untyped def begin_isolated_db_transaction: (untyped isolation) -> untyped # Commits a transaction. def commit_db_transaction: () -> untyped # Aborts a transaction. def exec_rollback_db_transaction: () -> untyped def execute_batch: (untyped statements, ?untyped? name) -> untyped def build_truncate_statements: (untyped table_names) -> ::Array[::String] # Returns the current ID of a table's sequence. def last_insert_id_result: (untyped sequence_name) -> untyped def suppress_composite_primary_key: (untyped pk) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL class ExplainPrettyPrinter # :nodoc: # Pretty prints the result of an EXPLAIN in a way that resembles the output of the # PostgreSQL shell: # # QUERY PLAN # ------------------------------------------------------------------------------ # Nested Loop Left Join (cost=0.00..37.24 rows=8 width=0) # Join Filter: (posts.user_id = users.id) # -> Index Scan using users_pkey on users (cost=0.00..8.27 rows=1 width=4) # Index Cond: (id = 1) # -> Seq Scan on posts (cost=0.00..28.88 rows=8 width=4) # Filter: (posts.user_id = 1) # (6 rows) # def pp: (untyped result) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Array[unchecked out Elem] < ActiveModel::Type::Value # :nodoc: # :nodoc: include ActiveModel::Type::Helpers::Mutable class Data < ::Struct[untyped] attr_accessor encoder(): untyped attr_accessor values(): untyped end attr_reader subtype: untyped attr_reader delimiter: untyped def initialize: (untyped subtype, ?::String delimiter) -> untyped def deserialize: (untyped value) -> untyped def cast: (untyped value) -> untyped def serialize: (untyped value) -> untyped def ==: (untyped other) -> untyped def type_cast_for_schema: (untyped value) -> untyped def map: (untyped value) { () -> untyped } -> untyped def changed_in_place?: (untyped raw_old_value, untyped new_value) -> untyped def force_equality?: (untyped value) -> untyped def type_cast_array: (untyped value, untyped method) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Bit < ActiveModel::Type::Value # :nodoc: # :nodoc: def `type`: () -> :bit def cast_value: (untyped value) -> untyped def serialize: (untyped value) -> untyped class Data def initialize: (untyped value) -> untyped def to_s: () -> untyped def binary?: () -> untyped def hex?: () -> untyped attr_reader value: untyped end end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class BitVarying < OID::Bit # :nodoc: # :nodoc: def `type`: () -> :bit_varying end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Bytea < ActiveModel::Type::Binary # :nodoc: # :nodoc: def deserialize: (untyped value) -> (nil | untyped) end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Cidr < ActiveModel::Type::Value # :nodoc: # :nodoc: def `type`: () -> :cidr def type_cast_for_schema: (untyped value) -> untyped def serialize: (untyped value) -> untyped def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Date < Type::Date # :nodoc: # :nodoc: def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class DateTime < Type::DateTime # :nodoc: # :nodoc: def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Decimal < ActiveModel::Type::Decimal # :nodoc: # :nodoc: def infinity: (?::Hash[untyped, untyped] options) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Enum < ActiveModel::Type::Value # :nodoc: # :nodoc: def `type`: () -> :enum def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Hstore < ActiveModel::Type::Value # :nodoc: # :nodoc: include ActiveModel::Type::Helpers::Mutable def `type`: () -> :hstore def deserialize: (untyped value) -> untyped def serialize: (untyped value) -> untyped def accessor: () -> untyped # Will compare the Hash equivalents of +raw_old_value+ and +new_value+. # By comparing hashes, this avoids an edge case where the order of # the keys change between the two hashes, and they would not be marked # as equal. def changed_in_place?: (untyped raw_old_value, untyped new_value) -> untyped HstorePair: untyped def escape_hstore: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Inet < Cidr # :nodoc: # :nodoc: def `type`: () -> :inet end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Jsonb < Type::Json # :nodoc: # :nodoc: def `type`: () -> :jsonb end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class LegacyPoint < ActiveModel::Type::Value # :nodoc: # :nodoc: include ActiveModel::Type::Helpers::Mutable def `type`: () -> :point def cast: (untyped value) -> untyped def serialize: (untyped value) -> untyped def number_for_point: (untyped number) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Money < ActiveModel::Type::Decimal # :nodoc: # :nodoc: def `type`: () -> :money def scale: () -> 2 def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Oid < Type::UnsignedInteger # :nodoc: # :nodoc: def `type`: () -> :oid end end end end end module ActiveRecord class Point < ::Struct[untyped] attr_accessor x(): untyped attr_accessor y(): untyped end module ConnectionAdapters module PostgreSQL module OID class Point < ActiveModel::Type::Value # :nodoc: # :nodoc: include ActiveModel::Type::Helpers::Mutable def `type`: () -> :point def cast: (untyped value) -> untyped def serialize: (untyped value) -> untyped def type_cast_for_schema: (untyped value) -> untyped def number_for_point: (untyped number) -> untyped def build_point: (untyped x, untyped y) -> ActiveRecord::Point end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Range[Elem] < ActiveModel::Type::Value # :nodoc: # :nodoc: attr_reader subtype: untyped # :nodoc: # :nodoc: attr_reader type: untyped def initialize: (untyped subtype, ?::Symbol `type`) -> untyped def type_cast_for_schema: (untyped value) -> untyped def cast_value: (untyped value) -> (nil | untyped) def serialize: (untyped value) -> untyped def ==: (untyped other) -> untyped def map: (untyped value) { (untyped) -> untyped } -> untyped def force_equality?: (untyped value) -> untyped def type_cast_single: (untyped value) -> untyped def type_cast_single_for_database: (untyped value) -> untyped def extract_bounds: (untyped value) -> { from: untyped, to: untyped, exclude_start: untyped, :exclude_end => untyped } def infinity: (?negative: bool negative) -> untyped def infinity?: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class SpecializedString < ActiveModel::Type::String # :nodoc: # :nodoc: attr_reader type: untyped def initialize: (untyped `type`, **untyped options) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class TypeMapInitializer # :nodoc: # This class uses the data from PostgreSQL pg_type table to build # the OID -> Type mapping. # - OID is an integer representing the type. # - Type is an OID::Type object. # This class has side effects on the +store+ passed during initialization. # :nodoc: def initialize: (untyped store) -> untyped def run: (untyped records) -> untyped def query_conditions_for_initial_load: () -> untyped def register_mapped_type: (untyped row) -> untyped def register_enum_type: (untyped row) -> untyped def register_array_type: (untyped row) -> untyped def register_range_type: (untyped row) -> untyped def register_domain_type: (untyped row) -> untyped def register_composite_type: (untyped row) -> untyped def register: (untyped oid, ?untyped? oid_type) { () -> untyped } -> untyped def alias_type: (untyped oid, untyped target) -> untyped def register_with_subtype: (untyped oid, untyped target_oid) { (untyped) -> untyped } -> untyped def assert_valid_registration: (untyped oid, untyped oid_type) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Uuid < ActiveModel::Type::Value # :nodoc: # :nodoc: ACCEPTABLE_UUID: untyped def `type`: () -> :uuid def cast_value: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Vector < ActiveModel::Type::Value # :nodoc: # :nodoc: attr_reader delim: untyped # :nodoc: # :nodoc: attr_reader subtype: untyped # +delim+ corresponds to the `typdelim` column in the pg_types # table. +subtype+ is derived from the `typelem` column in the # pg_types table. def initialize: (untyped delim, untyped subtype) -> untyped # FIXME: this should probably split on +delim+ and use +subtype+ # to cast the values. Unfortunately, the current Rails behavior # is to just return the string. def cast: (untyped value) -> untyped end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module OID class Xml < ActiveModel::Type::String # :nodoc: # :nodoc: def `type`: () -> :xml def serialize: (untyped value) -> (nil | Data) class Data # :nodoc: def initialize: (untyped value) -> untyped def to_s: () -> untyped end end end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module Quoting # Escapes binary strings for bytea input to the database. def escape_bytea: (untyped value) -> untyped # 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. def unescape_bytea: (untyped value) -> untyped def quote_string: (untyped s) -> untyped def quote_table_name: (untyped name) -> untyped # Quotes schema names for use in SQL queries. def quote_schema_name: (untyped name) -> untyped def quote_table_name_for_assignment: (untyped table, untyped attr) -> untyped def quote_column_name: (untyped name) -> untyped def quoted_date: (untyped value) -> untyped def quoted_binary: (untyped value) -> ::String def quote_default_expression: (untyped value, untyped column) -> untyped def lookup_cast_type_from_column: (untyped column) -> untyped def column_name_matcher: () -> untyped def column_name_with_order_matcher: () -> untyped COLUMN_NAME: untyped COLUMN_NAME_WITH_ORDER: untyped def lookup_cast_type: (untyped sql_type) -> untyped def _quote: (untyped value) -> untyped def _type_cast: (untyped value) -> untyped def encode_array: (untyped array_data) -> untyped def encode_range: (untyped range) -> ::String def determine_encoding_of_strings_in_array: (untyped value) -> untyped def type_cast_array: (untyped values) -> untyped def type_cast_range_value: (untyped value) -> untyped def infinity?: (untyped value) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module ReferentialIntegrity def disable_referential_integrity: () { () -> untyped } -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL class SchemaCreation < AbstractAdapter::SchemaCreation def visit_AlterTable: (untyped o) -> untyped def visit_AddForeignKey: (untyped o) -> untyped def visit_ValidateConstraint: (untyped name) -> ::String def visit_ChangeColumnDefinition: (untyped o) -> untyped def add_column_options!: (untyped sql, untyped options) -> untyped # Returns any SQL string to go between CREATE and TABLE. May be nil. def table_modifier_in_create: (untyped o) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module ColumnMethods extend ActiveSupport::Concern # 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. def primary_key: (untyped name, ?::Symbol `type`, **untyped options) -> untyped end class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition include ColumnMethods attr_reader unlogged: untyped def initialize: () -> untyped def integer_like_primary_key_type: (untyped `type`, untyped options) -> untyped end class Table < ActiveRecord::ConnectionAdapters::Table include ColumnMethods end class AlterTable < ActiveRecord::ConnectionAdapters::AlterTable attr_reader constraint_validations: untyped def initialize: (untyped td) -> untyped def validate_constraint: (untyped name) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL class SchemaDumper < ConnectionAdapters::SchemaDumper def extensions: (untyped stream) -> untyped def prepare_column_options: (untyped column) -> untyped def default_primary_key?: (untyped column) -> untyped def explicit_primary_key_default?: (untyped column) -> untyped def schema_type: (untyped column) -> untyped def schema_expression: (untyped column) -> untyped end end end end module ActiveRecord module ConnectionAdapters module PostgreSQL module SchemaStatements def recreate_database: (untyped name, ?::Hash[untyped, untyped] options) -> untyped # 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' def create_database: (untyped name, ?::Hash[untyped, untyped] options) -> untyped def drop_database: (untyped name) -> untyped def drop_table: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped # Returns true if schema exists. def schema_exists?: (untyped name) -> untyped # Verifies existence of an index with a given name. def index_name_exists?: (untyped table_name, untyped index_name) -> untyped def indexes: (untyped table_name) -> untyped def table_options: (untyped table_name) -> untyped def table_comment: (untyped table_name) -> untyped # Returns the current database name. def current_database: () -> untyped # Returns the current schema name. def current_schema: () -> untyped # Returns the current database encoding format. def encoding: () -> untyped # Returns the current database collation. def collation: () -> untyped # Returns the current database ctype. def ctype: () -> untyped # Returns an array of schema names. def schema_names: () -> untyped # Creates a schema for the given schema name. def create_schema: (untyped schema_name) -> untyped # Drops the schema for the given schema name. def drop_schema: (untyped schema_name, ?::Hash[untyped, untyped] options) -> untyped # 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: https://www.postgresql.org/docs/current/static/ddl-schemas.html # # This should be not be called manually but set in database.yml. def schema_search_path=: (untyped schema_csv) -> untyped # Returns the active schema search path. def schema_search_path: () -> untyped # Returns the current client message level. def client_min_messages: () -> untyped # Set the client message level. def client_min_messages=: (untyped level) -> untyped def default_sequence_name: (untyped table_name, ?::String pk) -> untyped def serial_sequence: (untyped table, untyped column) -> untyped def set_pk_sequence!: (untyped table, untyped value) -> untyped def reset_pk_sequence!: (untyped table, ?untyped? pk, ?untyped? sequence) -> untyped def pk_and_sequence_for: (untyped table) -> untyped def primary_keys: (untyped table_name) -> untyped # 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') def rename_table: (untyped table_name, untyped new_name) -> untyped def add_column: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> untyped def change_column: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def change_column_default: (untyped table_name, untyped column_name, untyped default_or_changes) -> untyped def change_column_null: (untyped table_name, untyped column_name, untyped null, ?untyped? default) -> untyped def change_column_comment: (untyped table_name, untyped column_name, untyped comment_or_changes) -> untyped def change_table_comment: (untyped table_name, untyped comment_or_changes) -> untyped def rename_column: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped def add_index: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> untyped def remove_index: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped # Renames an index of a table. Raises error if length of new # index name is greater than allowed limit. def rename_index: (untyped table_name, untyped old_name, untyped new_name) -> untyped def foreign_keys: (untyped table_name) -> untyped def foreign_tables: () -> untyped def foreign_table_exists?: (untyped table_name) -> untyped def type_to_sql: (untyped `type`, ?array: untyped? array, ?scale: untyped? scale, ?precision: untyped? precision, ?limit: untyped? limit) -> untyped def columns_for_distinct: (untyped columns, untyped orders) -> untyped def update_table_definition: (untyped table_name, untyped base) -> PostgreSQL::Table def create_schema_dumper: (untyped options) -> untyped # Validates the given constraint. # # Validates the constraint named +constraint_name+ on +accounts+. # # validate_constraint :accounts, :constraint_name def validate_constraint: (untyped table_name, untyped constraint_name) -> (nil | untyped) # 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. def validate_foreign_key: (untyped from_table, ?untyped? to_table, **untyped options) -> (nil | untyped) def schema_creation: () -> PostgreSQL::SchemaCreation def create_table_definition: (*untyped args, **untyped options) -> PostgreSQL::TableDefinition def create_alter_table: (untyped name) -> PostgreSQL::AlterTable def new_column_from_field: (untyped table_name, untyped field) -> PostgreSQL::Column def fetch_type_metadata: (untyped column_name, untyped sql_type, untyped oid, untyped fmod) -> PostgreSQL::TypeMetadata def sequence_name_from_parts: (untyped table_name, untyped column_name, untyped suffix) -> ::String def extract_foreign_key_action: (untyped specifier) -> untyped def add_column_for_alter: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> (untyped | ::Array[untyped]) def change_column_for_alter: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def change_column_default_for_alter: (untyped table_name, untyped column_name, untyped default_or_changes) -> (nil | untyped) def change_column_null_for_alter: (untyped table_name, untyped column_name, untyped null, ?untyped? default) -> ::String def add_index_opclass: (untyped quoted_columns, **untyped options) -> untyped def add_options_for_index_columns: (untyped quoted_columns, **untyped options) -> untyped def data_source_sql: (?untyped? name, ?type: untyped? `type`) -> untyped def quoted_scope: (?untyped? name, ?type: untyped? `type`) -> untyped def extract_schema_qualified_name: (untyped string) -> ::Array[untyped] end end end end module ActiveRecord # :stopdoc: module ConnectionAdapters module PostgreSQL # Note: It inherits unnamed class, but omitted class TypeMetadata attr_reader oid: untyped attr_reader fmod: untyped def initialize: (untyped type_metadata, ?fmod: untyped? fmod, ?oid: untyped? oid) -> untyped def ==: (untyped other) -> untyped def hash: () -> untyped end end PostgreSQLTypeMetadata: untyped end end module ActiveRecord module ConnectionAdapters module PostgreSQL class Name # Value Object to hold a schema qualified name. # This is usually the name of a PostgreSQL relation but it can also represent # schema qualified type names. +schema+ and +identifier+ are unquoted to prevent # double quoting. # :nodoc: SEPARATOR: ::String attr_reader schema: untyped attr_reader identifier: untyped def initialize: (untyped schema, untyped identifier) -> untyped def to_s: () -> untyped def quoted: () -> untyped def ==: (untyped o) -> untyped def hash: () -> untyped def parts: () -> untyped def unquote: (untyped part) -> untyped end module Utils # Returns an instance of ActiveRecord::ConnectionAdapters::PostgreSQL::Name # extracted from +string+. # +schema+ is +nil+ if not specified in +string+. # +schema+ and +identifier+ exclude surrounding quotes (regardless of whether provided in +string+) # +string+ supports the range of schema/table references understood by PostgreSQL, for example: # # * table_name # * "table.name" # * schema_name.table_name # * schema_name."table.name" # * "schema_name".table_name # * "schema.name"."table name" def extract_schema_qualified_name: (untyped string) -> PostgreSQL::Name end end end end module ActiveRecord module ConnectionAdapters class SchemaCache attr_reader version: untyped attr_accessor connection: untyped def initialize: (untyped conn) -> untyped def initialize_dup: (untyped other) -> untyped def encode_with: (untyped coder) -> untyped def init_with: (untyped coder) -> untyped def primary_keys: (untyped table_name) -> untyped # A cached lookup for table existence. def data_source_exists?: (untyped name) -> untyped # Add internal cache for table with +table_name+. def add: (untyped table_name) -> untyped def data_sources: (untyped name) -> untyped # Get the columns for a table def columns: (untyped table_name) -> untyped # Get the columns for a table as a hash, key is the column name # value is the column object. def columns_hash: (untyped table_name) -> untyped # Checks whether the columns hash is already cached for a table. def columns_hash?: (untyped table_name) -> untyped def indexes: (untyped table_name) -> untyped def database_version: () -> untyped # Clears out internal caches def clear!: () -> untyped def size: () -> untyped # Clear out internal caches for the data source +name+. def clear_data_source_cache!: (untyped name) -> untyped def marshal_dump: () -> ::Array[untyped] def marshal_load: (untyped array) -> untyped def prepare_data_sources: () -> untyped end end end module ActiveRecord module ConnectionHandling # :nodoc: def sqlite3_connection: (untyped config) -> untyped end module ConnectionAdapters # nodoc: # The SQLite3 adapter works SQLite 3.6.16 or newer # with the sqlite3-ruby drivers (available as gem from https://rubygems.org/gems/sqlite3). # # Options: # # * :database - Path to the database file. class SQLite3Adapter < AbstractAdapter ADAPTER_NAME: ::String include SQLite3::Quoting include SQLite3::SchemaStatements include SQLite3::DatabaseStatements NATIVE_DATABASE_TYPES: ::Hash[untyped, untyped] def self.represent_boolean_as_integer=: (untyped value) -> untyped class StatementPool < ConnectionAdapters::StatementPool def dealloc: (untyped stmt) -> untyped end def initialize: (untyped connection, untyped logger, untyped connection_options, untyped config) -> untyped def self.database_exists?: (untyped config) -> untyped def supports_ddl_transactions?: () -> ::TrueClass def supports_savepoints?: () -> ::TrueClass def supports_partial_index?: () -> ::TrueClass def supports_expression_index?: () -> untyped def requires_reloading?: () -> ::TrueClass def supports_foreign_keys?: () -> ::TrueClass def supports_views?: () -> ::TrueClass def supports_datetime_with_precision?: () -> ::TrueClass def supports_json?: () -> ::TrueClass def supports_common_table_expressions?: () -> untyped def supports_insert_on_conflict?: () -> untyped def active?: () -> untyped def reconnect!: () -> untyped # Disconnects from the database if already connected. Otherwise, this # method does nothing. def disconnect!: () -> untyped def supports_index_sort_order?: () -> ::TrueClass # Returns 62. SQLite supports index names up to 64 # characters. The rest is used by Rails internally to perform # temporary rename operations def allowed_index_name_length: () -> untyped def native_database_types: () -> untyped # Returns the current database encoding format as a string, eg: 'UTF-8' def encoding: () -> untyped def supports_explain?: () -> ::TrueClass def supports_lazy_transactions?: () -> ::TrueClass def disable_referential_integrity: () { () -> untyped } -> untyped # - # DATABASE STATEMENTS ====================================== # + def explain: (untyped arel, ?untyped binds) -> untyped def primary_keys: (untyped table_name) -> untyped def remove_index: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped # Renames a table. # # Example: # rename_table('octopuses', 'octopi') def rename_table: (untyped table_name, untyped new_name) -> untyped def add_column: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> untyped def remove_column: (untyped table_name, untyped column_name, ?untyped? `type`, **untyped options) -> untyped def change_column_default: (untyped table_name, untyped column_name, untyped default_or_changes) -> untyped def change_column_null: (untyped table_name, untyped column_name, untyped null, ?untyped? default) -> untyped def change_column: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def rename_column: (untyped table_name, untyped column_name, untyped new_column_name) -> untyped def add_reference: (untyped table_name, untyped ref_name, **untyped options) -> untyped def foreign_keys: (untyped table_name) -> untyped def build_insert_sql: (untyped insert) -> untyped def get_database_version: () -> AbstractAdapter::Version def check_version: () -> untyped # See https://www.sqlite.org/limits.html, # the default value is 999 when not configured. def bind_params_length: () -> 999 def initialize_type_map: (?untyped m) -> untyped def table_structure: (untyped table_name) -> untyped # See: https://www.sqlite.org/lang_altertable.html # SQLite has an additional restriction on the ALTER TABLE statement def invalid_alter_table_type?: (untyped `type`, untyped options) -> untyped def alter_table: (untyped table_name, ?untyped foreign_keys, **untyped options) { (untyped) -> untyped } -> untyped def move_table: (untyped from, untyped to, ?::Hash[untyped, untyped] options) { () -> untyped } -> untyped def copy_table: (untyped from, untyped to, ?::Hash[untyped, untyped] options) { (untyped) -> untyped } -> untyped def copy_table_indexes: (untyped from, untyped to, ?::Hash[untyped, untyped] rename) -> untyped def copy_table_contents: (untyped from, untyped to, untyped columns, ?::Hash[untyped, untyped] rename) -> untyped def translate_exception: (untyped exception, binds: untyped binds, sql: untyped sql, message: untyped message) -> untyped COLLATE_REGEX: untyped def table_structure_with_collation: (untyped table_name, untyped basic_structure) -> untyped def arel_visitor: () -> Arel::Visitors::SQLite def build_statement_pool: () -> StatementPool def connect: () -> untyped def configure_connection: () -> untyped class SQLite3Integer < ActiveModel::Type::Integer def _limit: () -> untyped end end end end module ActiveRecord module ConnectionAdapters module SQLite3 module DatabaseStatements READ_QUERY: untyped def write_query?: (untyped sql) -> untyped def execute: (untyped sql, ?untyped? name) -> untyped def exec_query: (untyped sql, ?untyped? name, ?untyped binds, ?prepare: bool prepare) -> untyped def exec_delete: (untyped sql, ?::String name, ?untyped binds) -> untyped def begin_db_transaction: () -> untyped def commit_db_transaction: () -> untyped def exec_rollback_db_transaction: () -> untyped def execute_batch: (untyped statements, ?untyped? name) -> untyped def last_inserted_id: (untyped result) -> untyped def build_fixture_statements: (untyped fixture_set) -> untyped def build_truncate_statement: (untyped table_name) -> ::String end end end end module ActiveRecord module ConnectionAdapters module SQLite3 class ExplainPrettyPrinter # :nodoc: # Pretty prints the result of an EXPLAIN QUERY PLAN in a way that resembles # the output of the SQLite shell: # # 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) # 0|1|1|SCAN TABLE posts (~100000 rows) # def pp: (untyped result) -> untyped end end end end module ActiveRecord module ConnectionAdapters module SQLite3 module Quoting # :nodoc: def quote_string: (untyped s) -> untyped def quote_table_name_for_assignment: (untyped table, untyped attr) -> untyped def quote_table_name: (untyped name) -> untyped def quote_column_name: (untyped name) -> untyped def quoted_time: (untyped value) -> untyped def quoted_binary: (untyped value) -> ::String def quoted_true: () -> "1" def unquoted_true: () -> 1 def quoted_false: () -> "0" def unquoted_false: () -> 0 def column_name_matcher: () -> untyped def column_name_with_order_matcher: () -> untyped COLUMN_NAME: untyped COLUMN_NAME_WITH_ORDER: untyped def _type_cast: (untyped value) -> untyped end end end end module ActiveRecord module ConnectionAdapters module SQLite3 class SchemaCreation < AbstractAdapter::SchemaCreation def add_column_options!: (untyped sql, untyped options) -> untyped end end end end module ActiveRecord module ConnectionAdapters module SQLite3 class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition def references: (*untyped args, **untyped options) -> untyped def integer_like_primary_key_type: (untyped `type`, untyped options) -> :primary_key end end end end module ActiveRecord module ConnectionAdapters module SQLite3 class SchemaDumper < ConnectionAdapters::SchemaDumper def default_primary_key?: (untyped column) -> untyped def explicit_primary_key_default?: (untyped column) -> untyped end end end end module ActiveRecord module ConnectionAdapters module SQLite3 module SchemaStatements # :nodoc: # Returns an array of indexes for the given table. def indexes: (untyped table_name) -> untyped def add_foreign_key: (untyped from_table, untyped to_table, **untyped options) -> untyped def remove_foreign_key: (untyped from_table, ?untyped? to_table, **untyped options) -> untyped def create_schema_dumper: (untyped options) -> untyped def schema_creation: () -> SQLite3::SchemaCreation def create_table_definition: (*untyped args, **untyped options) -> SQLite3::TableDefinition def new_column_from_field: (untyped table_name, untyped field) -> Column def data_source_sql: (?untyped? name, ?type: untyped? `type`) -> untyped def quoted_scope: (?untyped? name, ?type: untyped? `type`) -> untyped end end end end module ActiveRecord # :stopdoc: module ConnectionAdapters class SqlTypeMetadata attr_reader sql_type: untyped attr_reader type: untyped attr_reader limit: untyped attr_reader precision: untyped attr_reader scale: untyped def initialize: (?scale: untyped? scale, ?precision: untyped? precision, ?limit: untyped? limit, ?type: untyped? `type`, ?sql_type: untyped? sql_type) -> untyped def ==: (untyped other) -> untyped def hash: () -> untyped end end end module ActiveRecord module ConnectionAdapters class StatementPool # :nodoc: include Enumerable[untyped, untyped] DEFAULT_STATEMENT_LIMIT: ::Integer def initialize: (?untyped? statement_limit) -> untyped def each: () { () -> untyped } -> untyped def key?: (untyped key) -> untyped def []: (untyped key) -> untyped def length: () -> untyped def []=: (untyped sql, untyped stmt) -> untyped def clear: () -> untyped def delete: (untyped key) -> untyped def cache: () -> untyped def dealloc: (untyped stmt) -> untyped end end end module ActiveRecord module ConnectionHandling RAILS_ENV: untyped DEFAULT_ENV: untyped # 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}[rdoc-ref:Core.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. def establish_connection: (?untyped? config_or_env) -> untyped # 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 # # Returns an array of established connections. def connects_to: (?database: ::Hash[untyped, untyped] database) -> untyped # Connects to a database or role (ex writing, reading, or another # custom role) for the duration of the block. # # If a role is passed, Active Record will look up the connection # based on the requested role: # # 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 # # ActiveRecord::Base.connected_to(role: :unknown_role) do # # raises exception due to non-existent role # end # # The `database` kwarg is deprecated in 6.1 and will be removed in 6.2 # # It is not recommended for use as it re-establishes a connection every # time it is called. def connected_to: (?prevent_writes: bool prevent_writes, ?role: untyped? role, ?database: untyped? database) { () -> untyped } -> untyped # 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 def connected_to?: (role: untyped role) -> untyped # 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 def current_role: () -> untyped def lookup_connection_handler: (untyped handler_key) -> untyped def with_handler: (untyped handler_key) { () -> untyped } -> untyped def resolve_config_for_connection: (untyped config_or_env) -> untyped # Clears the query cache for all connections associated with the current thread. def clear_query_caches_for_current_thread: () -> untyped # 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. def connection: () -> untyped attr_writer connection_specification_name: untyped # Return the specification name from the current class or its parent. def connection_specification_name: () -> untyped def primary_class?: () -> untyped # Returns the configuration of the associated connection as a hash: # # ActiveRecord::Base.connection_config # # => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"} # # Please use only for reading. def connection_config: () -> untyped def connection_pool: () -> untyped def retrieve_connection: () -> untyped # Returns +true+ if Active Record is connected. def connected?: () -> untyped def remove_connection: (?untyped? name) -> untyped def clear_cache!: () -> untyped def swap_connection_handler: (untyped handler) { () -> untyped } -> untyped end end module ActiveRecord module Core extend ActiveSupport::Concern # # 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: # # #"sqlite3", "database"=>"db/development.sqlite3"}>, # #"mysql2", "database"=>"db/production.sqlite3"}> # ]> def self.configurations=: (untyped config) -> untyped # Returns fully resolved ActiveRecord::DatabaseConfigurations object def self.configurations: () -> untyped def self.connection_handler: () -> untyped def self.connection_handler=: (untyped handler) -> untyped module ClassMethods def initialize_find_by_cache: () -> untyped def inherited: (untyped child_class) -> untyped def find: (*untyped ids) -> untyped def find_by: (*untyped args) -> untyped def find_by!: (*untyped args) -> untyped def initialize_generated_modules: () -> untyped def generated_association_methods: () -> untyped # Returns columns which shouldn't be exposed while calling +#inspect+. def filter_attributes: () -> untyped # Specifies columns which shouldn't be exposed while calling +#inspect+. attr_writer filter_attributes: untyped def inspect: () -> untyped def ===: (untyped object) -> untyped def arel_table: () -> untyped def arel_attribute: (untyped name, ?untyped table) -> untyped def predicate_builder: () -> untyped def type_caster: () -> TypeCaster::Map def _internal?: () -> ::FalseClass def cached_find_by_statement: (untyped key) { () -> untyped } -> untyped def relation: () -> untyped def table_metadata: () -> TableMetadata end # 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') def initialize: (?untyped? attributes) { (untyped) -> untyped } -> untyped # 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' def init_with: (untyped coder) { () -> untyped } -> untyped def init_with_attributes: (untyped attributes, ?bool new_record) { (untyped) -> untyped } -> untyped def initialize_dup: (untyped other) -> untyped # 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, ... }} def encode_with: (untyped coder) -> untyped # 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. def ==: (untyped comparison_object) -> untyped # 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) ] def hash: () -> untyped # Clone and freeze the attributes hash such that associations are still # accessible, even on destroyed records, but cloned models will not be # frozen. def freeze: () -> untyped # Returns +true+ if the attributes hash has been frozen. def frozen?: () -> untyped # Allows sort on objects def <=>: (untyped other_object) -> untyped def present?: () -> ::TrueClass def blank?: () -> ::FalseClass # Returns +true+ if the record is read only. Records loaded through joins with piggy-back # attributes will be marked as read only since they cannot be saved. def readonly?: () -> untyped # Marks this record as read only. def readonly!: () -> untyped def connection_handler: () -> untyped # Returns the contents of the record as a nicely formatted string. def inspect: () -> ::String # Takes a PP and prettily prints this record to it, allowing you to get a nice result from pp record # when pp is required. def pretty_print: (untyped pp) -> untyped # Returns a hash of the given methods with their names as keys and returned values as values. def slice: (*untyped methods) -> untyped # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of # the array, and then rescues from the possible +NoMethodError+. If those elements are # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have, # which significantly impacts upon performance. # # So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here. # # See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html def to_ary: () -> nil def init_internals: () -> untyped def initialize_internals_callback: () -> nil def custom_inspect_method_defined?: () -> untyped # Note: It inherits unnamed class, but omitted class InspectionMask def pretty_print: (untyped pp) -> untyped end def inspection_filter: () -> untyped end end module ActiveRecord # = Active Record Counter Cache module CounterCache extend ActiveSupport::Concern module ClassMethods # 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) def reset_counters: (untyped id, *untyped counters, ?touch: untyped? touch) -> ::TrueClass # 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) def update_counters: (untyped id, untyped counters) -> untyped # 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) def increment_counter: (untyped counter_name, untyped id, ?touch: untyped? touch) -> untyped # 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) def decrement_counter: (untyped counter_name, untyped id, ?touch: untyped? touch) -> untyped end def _create_record: (?untyped attribute_names) -> untyped def destroy_row: () -> untyped def each_counter_cached_associations: () { (untyped) -> untyped } -> untyped end end module ActiveRecord class DatabaseConfigurations class DatabaseConfig # ActiveRecord::Base.configurations will return either a HashConfig or # UrlConfig respectively. It will never return a DatabaseConfig object, # as this is the parent class for the types of database configuration objects. # :nodoc: attr_reader env_name: untyped # ActiveRecord::Base.configurations will return either a HashConfig or # UrlConfig respectively. It will never return a DatabaseConfig object, # as this is the parent class for the types of database configuration objects. # :nodoc: attr_reader spec_name: untyped def initialize: (untyped env_name, untyped spec_name) -> untyped def replica?: () -> untyped def migrations_paths: () -> untyped def url_config?: () -> ::FalseClass def to_legacy_hash: () -> ::Hash[untyped, untyped] def for_current_env?: () -> untyped end end end module ActiveRecord class DatabaseConfigurations # A HashConfig object is created for each database configuration entry that # is created from a hash. # # A hash config: # # { "development" => { "database" => "db_name" } } # # Becomes: # # #"db_name"}> # # ==== Options # # * :env_name - The Rails environment, i.e. "development". # * :spec_name - The specification 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. class HashConfig < DatabaseConfig attr_reader config: untyped def initialize: (untyped env_name, untyped spec_name, untyped config) -> untyped # Determines whether a database configuration is for a replica / readonly # connection. If the +replica+ key is present in the config, +replica?+ will # return +true+. def replica?: () -> untyped # The migrations paths for a database configuration. If the # +migrations_paths+ key is present in the config, +migrations_paths+ # will return its value. def migrations_paths: () -> untyped end end end module ActiveRecord # 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. class DatabaseConfigurations class InvalidConfigurationError < StandardError end attr_reader configurations: untyped def initialize: (?::Hash[untyped, untyped] configurations) -> untyped # Collects the configs for the environment and optionally the specification # name passed in. To include replica configurations pass include_replicas: true. # # If a spec 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. # * spec_name: The specification name (i.e. primary, animals, etc.). Defaults # to +nil+. # * include_replicas: 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+. def configs_for: (?include_replicas: bool include_replicas, ?spec_name: untyped? spec_name, ?env_name: untyped? env_name) -> untyped # Returns the config hash that corresponds with the environment # # If the application has multiple databases +default_hash+ will # return the first config hash for the environment. # # { database: "my_db", adapter: "mysql2" } def default_hash: (?untyped env) -> untyped # 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. def find_db_config: (untyped env) -> untyped # Returns the DatabaseConfigurations object as a Hash. def to_h: () -> untyped # Checks if the application's configurations are empty. # # Aliased to blank? def empty?: () -> untyped def each: () { (untyped) -> untyped } -> untyped def first: () -> ::Array[untyped] def env_with_configs: (?untyped? env) -> untyped def build_configs: (untyped configs) -> untyped def walk_configs: (untyped env_name, untyped config) -> untyped def build_db_config_from_raw_config: (untyped env_name, untyped spec_name, untyped config) -> untyped def build_db_config_from_string: (untyped env_name, untyped spec_name, untyped config) -> untyped def build_db_config_from_hash: (untyped env_name, untyped spec_name, untyped config) -> untyped def merge_db_environment_variables: (untyped current_env, untyped configs) -> untyped def environment_url_config: (untyped env, untyped spec_name, untyped config) -> (nil | ActiveRecord::DatabaseConfigurations::UrlConfig) def environment_value_for: (untyped spec_name) -> untyped def method_missing: (untyped method, *untyped args) { () -> untyped } -> untyped def throw_setter_deprecation: (untyped method) -> untyped def throw_getter_deprecation: (untyped method) -> untyped end end module ActiveRecord class DatabaseConfigurations # 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: # # #"postgresql", "database"=>"foo", "host"=>"localhost"}, # @url="postgres://localhost/foo"> # # ==== Options # # * :env_name - The Rails environment, ie "development". # * :spec_name - The specification 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. class UrlConfig < DatabaseConfig attr_reader url: untyped attr_reader config: untyped def initialize: (untyped env_name, untyped spec_name, untyped url, ?::Hash[untyped, untyped] config) -> untyped def url_config?: () -> ::TrueClass # Determines whether a database configuration is for a replica / readonly # connection. If the +replica+ key is present in the config, +replica?+ will # return +true+. def replica?: () -> untyped # The migrations paths for a database configuration. If the # +migrations_paths+ key is present in the config, +migrations_paths+ # will return its value. def migrations_paths: () -> untyped def build_url_hash: (untyped url) -> untyped def build_config: (untyped original_config, untyped url) -> untyped end end end module ActiveRecord # This module exists because ActiveRecord::AttributeMethods::Dirty needs to # define callbacks, but continue to have its version of +save+ be the super # method of ActiveRecord::Callbacks. This will be removed when the removal # of deprecated code removes this need. module DefineCallbacks extend ActiveSupport::Concern module ClassMethods # :nodoc: include ActiveModel::Callbacks end include ActiveModel::Validations::Callbacks extend ::ActiveModel::Validations::Callbacks::ClassMethods end end module ActiveRecord module DynamicMatchers def respond_to_missing?: (untyped name, untyped _) -> untyped def method_missing: (untyped name, *untyped arguments) { () -> untyped } -> untyped class Method attr_reader matchers: untyped def self.match: (untyped model, untyped name) -> untyped def self.pattern: () -> untyped def self.prefix: () -> untyped def self.suffix: () -> ::String attr_reader model: untyped attr_reader name: untyped attr_reader attribute_names: untyped def initialize: (untyped model, untyped method_name) -> untyped def valid?: () -> untyped def define: () -> untyped def body: () -> ::String # The parameters in the signature may have reserved Ruby words, in order # to prevent errors, we start each param name with `_`. def signature: () -> untyped # Given that the parameters starts with `_`, the finder needs to use the # same parameter name. def attributes_hash: () -> untyped def finder: () -> untyped end class FindBy < Method def self.prefix: () -> "find_by" def finder: () -> "find_by" end class FindByBang < Method def self.prefix: () -> "find_by" def self.suffix: () -> "!" def finder: () -> "find_by!" end end end module ActiveRecord module Enum def self.extended: (untyped base) -> untyped def inherited: (untyped base) -> untyped class EnumType < ActiveModel::Type::Value def initialize: (untyped name, untyped mapping, untyped subtype) -> untyped def cast: (untyped value) -> (nil | untyped) def deserialize: (untyped value) -> (nil | untyped) def serialize: (untyped value) -> untyped def assert_valid_value: (untyped value) -> untyped attr_reader name: untyped attr_reader mapping: untyped attr_reader subtype: untyped end def enum: (untyped definitions) -> untyped def _enum_methods_module: () -> untyped def assert_valid_enum_definition_values: (untyped values) -> untyped ENUM_CONFLICT_MESSAGE: ::String def detect_enum_conflict!: (untyped enum_name, untyped method_name, ?bool klass_method) -> untyped def raise_conflict_error: (untyped enum_name, untyped method_name, ?source: ::String source, ?type: ::String `type`) -> untyped def detect_negative_condition!: (untyped method_name) -> untyped end end module ActiveRecord # = Active Record Errors # # Generic Active Record exception class. class ActiveRecordError < StandardError end # 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}[rdoc-ref:ModelSchema::ClassMethods#inheritance_column] # points to). class SubclassNotFound < ActiveRecordError end # 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.") class AssociationTypeMismatch < ActiveRecordError end # Raised when unserialized object's type mismatches one specified for serializable field. class SerializationTypeMismatch < ActiveRecordError end # Raised when adapter not specified on connection (or configuration file # +config/database.yml+ misses adapter field). class AdapterNotSpecified < ActiveRecordError end # Raised when Active Record cannot find database adapter specified in # +config/database.yml+ or programmatically. class AdapterNotFound < ActiveRecordError end # Raised when connection to the database could not been established (for example when # {ActiveRecord::Base.connection=}[rdoc-ref:ConnectionHandling#connection] # is given a +nil+ object). class ConnectionNotEstablished < ActiveRecordError end # Raised when a write to the database is attempted on a read only connection. class ReadOnlyError < ActiveRecordError end # Raised when Active Record cannot find a record by given id or set of ids. class RecordNotFound < ActiveRecordError attr_reader model: untyped attr_reader primary_key: untyped attr_reader id: untyped def initialize: (?untyped? message, ?untyped? model, ?untyped? primary_key, ?untyped? id) -> untyped end # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!] # methods when a record is invalid and cannot be saved. class RecordNotSaved < ActiveRecordError attr_reader record: untyped def initialize: (?untyped? message, ?untyped? record) -> untyped end # Raised by {ActiveRecord::Base#destroy!}[rdoc-ref:Persistence#destroy!] # when a call to {#destroy}[rdoc-ref:Persistence#destroy!] # would return false. # # begin # complex_operation_that_internally_calls_destroy! # rescue ActiveRecord::RecordNotDestroyed => invalid # puts invalid.record.errors # end # class RecordNotDestroyed < ActiveRecordError attr_reader record: untyped def initialize: (?untyped? message, ?untyped? record) -> untyped end # Superclass for all database execution errors. # # Wraps the underlying database error as +cause+. class StatementInvalid < ActiveRecordError def initialize: (?untyped? message, ?binds: untyped? binds, ?sql: untyped? sql) -> untyped attr_reader sql: untyped attr_reader binds: untyped end # Defunct wrapper class kept for compatibility. # StatementInvalid wraps the original exception now. class WrappedDatabaseException < StatementInvalid end # Raised when a record cannot be inserted or updated because it would violate a uniqueness constraint. class RecordNotUnique < WrappedDatabaseException end # 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. class InvalidForeignKey < WrappedDatabaseException end # Raised when a foreign key constraint cannot be added because the column type does not match the referenced column type. class MismatchedForeignKey < StatementInvalid def initialize: (?primary_key_column: untyped? primary_key_column, ?primary_key: untyped? primary_key, ?target_table: untyped? target_table, ?foreign_key: untyped? foreign_key, ?table: untyped? table, ?binds: untyped? binds, ?sql: untyped? sql, ?message: untyped? message) -> untyped end # Raised when a record cannot be inserted or updated because it would violate a not null constraint. class NotNullViolation < StatementInvalid end # Raised when a record cannot be inserted or updated because a value too long for a column type. class ValueTooLong < StatementInvalid end # Raised when values that executed are out of range. class RangeError < StatementInvalid end # Raised when number of bind variables in statement given to +:condition+ key # (for example, when using {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method) # does not match number of expected values supplied. # # For example, when there are two placeholders with only one value supplied: # # Location.where("lat = ? AND lng = ?", 53.7362) class PreparedStatementInvalid < ActiveRecordError end # Raised when a given database does not exist. class NoDatabaseError < StatementInvalid end # Raised when PostgreSQL returns 'cached plan must not change result type' and # we cannot retry gracefully (e.g. inside a transaction) class PreparedStatementCacheExpired < StatementInvalid end # 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. class StaleObjectError < ActiveRecordError attr_reader record: untyped attr_reader attempted_action: untyped def initialize: (?untyped? record, ?untyped? attempted_action) -> untyped end # Raised when association is being configured improperly or user tries to use # offset and limit together with # {ActiveRecord::Base.has_many}[rdoc-ref:Associations::ClassMethods#has_many] or # {ActiveRecord::Base.has_and_belongs_to_many}[rdoc-ref:Associations::ClassMethods#has_and_belongs_to_many] # associations. class ConfigurationError < ActiveRecordError end # Raised on attempt to update record that is instantiated as read only. class ReadOnlyRecord < ActiveRecordError end # {ActiveRecord::Base.transaction}[rdoc-ref:Transactions::ClassMethods#transaction] # uses this exception to distinguish a deliberate rollback from other exceptional situations. # Normally, raising an exception will cause the # {.transaction}[rdoc-ref:Transactions::ClassMethods#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, "Call tech support!" # 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 class Rollback < ActiveRecordError end # Raised when attribute has a name reserved by Active Record (when attribute # has name of one of Active Record instance methods). class DangerousAttributeError < ActiveRecordError end # Raised when unknown attributes are supplied via mass assignment. UnknownAttributeError: untyped # Raised when an error occurred while doing a mass assignment to an attribute through the # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method. # The exception has an +attribute+ property that is the name of the offending attribute. class AttributeAssignmentError < ActiveRecordError attr_reader exception: untyped attr_reader attribute: untyped def initialize: (?untyped? message, ?untyped? exception, ?untyped? attribute) -> untyped end # Raised when there are multiple errors while doing a mass assignment through the # {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#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. class MultiparameterAssignmentErrors < ActiveRecordError attr_reader errors: untyped def initialize: (?untyped? errors) -> untyped end # Raised when a primary key is needed, but not specified in the schema or model. class UnknownPrimaryKey < ActiveRecordError attr_reader model: untyped def initialize: (?untyped? model, ?untyped? description) -> untyped end # 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 class ImmutableRelation < ActiveRecordError end # 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. class TransactionIsolationError < ActiveRecordError end # TransactionRollbackError will be raised when a transaction is rolled # back by the database due to a serialization failure or a deadlock. # # See the following: # # * https://www.postgresql.org/docs/current/static/transaction-iso.html # * https://dev.mysql.com/doc/refman/5.7/en/error-messages-server.html#error_er_lock_deadlock class TransactionRollbackError < StatementInvalid end # SerializationFailure will be raised when a transaction is rolled # back by the database due to a serialization failure. class SerializationFailure < TransactionRollbackError end # Deadlocked will be raised when a transaction is rolled # back by the database when a deadlock is encountered. class Deadlocked < TransactionRollbackError end # IrreversibleOrderError is raised when a relation's order is too complex for # +reverse_order+ to automatically reverse. class IrreversibleOrderError < ActiveRecordError end # LockWaitTimeout will be raised when lock wait timeout exceeded. class LockWaitTimeout < StatementInvalid end # StatementTimeout will be raised when statement timeout exceeded. class StatementTimeout < StatementInvalid end # QueryCanceled will be raised when canceling statement due to user request. class QueryCanceled < StatementInvalid end # UnknownAttributeReference is raised when an unknown and potentially unsafe # value is passed to a query method when allow_unsafe_raw_sql is set to # :disabled. 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, with allow_unsafe_raw_sql set to :disabled, the following # code would raise this exception: # # Post.order("length(title)").first # # The desired result can be accomplished by wrapping the known-safe string # in Arel.sql: # # Post.order(Arel.sql("length(title)")).first # # Again, such a workaround should *not* be used when passing user-provided # values, such as request parameters or model attributes to query methods. class UnknownAttributeReference < ActiveRecordError end end module ActiveRecord module Explain def collecting_queries_for_explain: () { () -> untyped } -> untyped def exec_explain: (untyped queries) -> untyped def render_bind: (untyped attr) -> ::Array[untyped] end end module ActiveRecord class ExplainRegistry # This is a thread locals registry for EXPLAIN. For example # # ActiveRecord::ExplainRegistry.queries # # returns the collected queries local to the current thread. # # See the documentation of ActiveSupport::PerThreadRegistry # for further details. # :nodoc: extend ActiveSupport::PerThreadRegistry attr_accessor queries: untyped attr_accessor collect: untyped def initialize: () -> untyped def collect?: () -> untyped def reset: () -> untyped end end module ActiveRecord class ExplainSubscriber # :nodoc: def start: (untyped name, untyped id, untyped payload) -> nil def finish: (untyped name, untyped id, untyped payload) -> untyped # SCHEMA queries cannot be EXPLAINed, also we do not want to run EXPLAIN on # our own EXPLAINs no matter how loopingly beautiful that would be. # # On the other hand, we want to monitor the performance of our real database # queries, not the performance of the access to the query cache. IGNORED_PAYLOADS: ::Array[untyped] EXPLAINED_SQLS: untyped def ignore_payload?: (untyped payload) -> untyped end end module ActiveRecord class FixtureSet class File # :nodoc: include Enumerable[untyped, untyped] # # Open a fixture file named +file+. When called with a block, the block # is called with the filehandle and the filehandle is automatically closed # when the block finishes. def self.open: (untyped file) { (untyped) -> untyped } -> untyped def initialize: (untyped file) -> untyped def each: () { () -> untyped } -> untyped def model_class: () -> untyped def rows: () -> untyped def config_row: () -> untyped def raw_rows: () -> untyped def prepare_erb: (untyped content) -> untyped def render: (untyped content) -> untyped # Validate our unmarshalled data. def validate: (untyped data) -> untyped end end end module ActiveRecord class FixtureSet class ModelMetadata # :nodoc: def initialize: (untyped model_class) -> untyped def primary_key_name: () -> untyped def primary_key_type: () -> untyped def has_primary_key_column?: () -> untyped def timestamp_column_names: () -> untyped def inheritance_column_name: () -> untyped end end end class ActiveRecord::FixtureSet::RenderContext # NOTE: This class has to be defined in compact style in # order for rendering context subclassing to work correctly. # :nodoc: def self.create_subclass: () -> untyped end module ActiveRecord class FixtureSet class TableRow class ReflectionProxy # :nodoc: # :nodoc: def initialize: (untyped association) -> untyped def join_table: () -> untyped def name: () -> untyped def primary_key_type: () -> untyped end class HasManyThroughProxy < ReflectionProxy # :nodoc: def rhs_key: () -> untyped def lhs_key: () -> untyped def join_table: () -> untyped end def initialize: (untyped fixture, now: untyped now, label: untyped label, table_rows: untyped table_rows) -> untyped def to_hash: () -> untyped def model_metadata: () -> untyped def model_class: () -> untyped def fill_row_model_attributes: () -> (nil | untyped) def reflection_class: () -> untyped def fill_timestamps: () -> untyped def interpolate_label: () -> untyped def generate_primary_key: () -> untyped def resolve_enums: () -> untyped def resolve_sti_reflections: () -> untyped def add_join_records: (untyped association) -> untyped end end end module ActiveRecord class FixtureSet class TableRows # :nodoc: def initialize: (untyped table_name, config: untyped config, fixtures: untyped fixtures, model_class: untyped model_class) -> untyped attr_reader tables: untyped attr_reader model_class: untyped def to_hash: () -> untyped def model_metadata: () -> untyped def build_table_rows_from: (untyped table_name, untyped fixtures, untyped config) -> untyped end end end module ActiveRecord class FixtureClassNotFound < ActiveRecord::ActiveRecordError end # \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 /test/fixtures/). # The fixture file ends with the +.yml+ file extension, for example: # /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 (ie. 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 http://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) # Digest::SHA2.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 `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 # # 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_s(:db) %> # # first: # name: Smurf # <<: *DEFAULTS # # second: # name: Fraggle # <<: *DEFAULTS # # Any fixture labeled "DEFAULTS" is safely ignored. # # == 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 rails db:fixtures:load). # # _fixture: # model_class: User # david: # name: David # # Any fixtures labeled "_fixture" are safely ignored. class FixtureSet MAX_ID: untyped class ClassCache def initialize: (untyped class_names, untyped config) -> untyped def []: (untyped fs_name) -> untyped def insert_class: (untyped class_names, untyped name, untyped klass) -> untyped def default_fixture_model: (untyped fs_name, untyped config) -> untyped end def self.default_fixture_model_name: (untyped fixture_set_name, ?untyped config) -> untyped def self.default_fixture_table_name: (untyped fixture_set_name, ?untyped config) -> untyped def self.reset_cache: () -> untyped def self.cache_for_connection: (untyped connection) -> untyped def self.fixture_is_cached?: (untyped connection, untyped table_name) -> untyped def self.cached_fixtures: (untyped connection, ?untyped? keys_to_fetch) -> untyped def self.cache_fixtures: (untyped connection, untyped fixtures_map) -> untyped def self.instantiate_fixtures: (untyped object, untyped fixture_set, ?bool load_instances) -> (nil | untyped) def self.instantiate_all_loaded_fixtures: (untyped object, ?bool load_instances) -> untyped def self.create_fixtures: (untyped fixtures_directory, untyped fixture_set_names, ?::Hash[untyped, untyped] class_names, ?untyped config) { () -> untyped } -> untyped # 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. def self.identify: (untyped label, ?::Symbol column_type) -> untyped # Superclass for the evaluation contexts used by ERB fixtures. def self.context_class: () -> untyped def self.read_and_insert: (untyped fixtures_directory, untyped fixture_files, untyped class_names, untyped connection) -> untyped def self.insert: (untyped fixture_sets, untyped connection) -> untyped def self.update_all_loaded_fixtures: (untyped fixtures_map) -> untyped attr_reader table_name: untyped attr_reader name: untyped attr_reader fixtures: untyped attr_reader model_class: untyped attr_reader config: untyped def initialize: (untyped _, untyped name, untyped class_name, untyped path, ?untyped config) -> untyped def []: (untyped x) -> untyped def []=: (untyped k, untyped v) -> untyped def each: () { () -> untyped } -> untyped def size: () -> untyped # 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. def table_rows: () -> untyped def model_class=: (untyped class_name) -> untyped # Loads the fixtures from the YAML file at +path+. # If the file sets the +model_class+ and current instance value is not set, # it uses the file value. def read_fixture_files: (untyped path) -> untyped def yaml_file_path: (untyped path) -> ::String end class Fixture # nodoc: include Enumerable[untyped, untyped] class FixtureError < StandardError end class FormatError < FixtureError end attr_reader model_class: untyped attr_reader fixture: untyped def initialize: (untyped fixture, untyped model_class) -> untyped def class_name: () -> untyped def each: () { (untyped) -> untyped } -> untyped def []: (untyped key) -> untyped def find: () -> untyped end end module ActiveRecord # Returns the version of the currently loaded Active Record as a Gem::Version def self.gem_version: () -> Gem::Version module VERSION MAJOR: ::Integer MINOR: ::Integer TINY: ::Integer PRE: ::String STRING: untyped end end module ActiveRecord # == 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: # https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html # module Inheritance extend ActiveSupport::Concern module ClassMethods # 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. def new: (?untyped? attributes) { () -> untyped } -> untyped # Returns +true+ if this does not need STI type condition. Returns # +false+ if STI type condition needs to be applied. def descends_from_active_record?: () -> untyped def finder_needs_type_condition?: () -> untyped # 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. def base_class: () -> untyped # Returns whether the class is a base class. # See #base_class for more information. def base_class?: () -> untyped # 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! # => # # Polygon.create! # => # # Square.create! # => # # # 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! # => # # Square.create! # => # # # 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. attr_accessor abstract_class: untyped # Returns whether this class is an abstract class or not. def abstract_class?: () -> untyped def sti_name: () -> untyped def polymorphic_name: () -> untyped def inherited: (untyped subclass) -> untyped # 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. def compute_type: (untyped type_name) -> untyped # Called by +instantiate+ to decide which class to use for a new # record instance. For single-table inheritance, we check the record # for a +type+ column and return the corresponding class. def discriminate_class_for_record: (untyped record) -> untyped def using_single_table_inheritance?: (untyped record) -> untyped def find_sti_class: (untyped type_name) -> untyped def type_condition: (?untyped table) -> untyped # Detect the subclass from the inheritance column of attrs. If the inheritance column value # is not self or a valid subclass, raises ActiveRecord::SubclassNotFound def subclass_from_attributes: (untyped attrs) -> untyped end def initialize_dup: (untyped other) -> untyped def initialize_internals_callback: () -> untyped # Sets the attribute used for single table inheritance to this class name if this is not the # ActiveRecord::Base descendant. # Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it possible to # do Reply.new without having to set Reply[Reply.inheritance_column] = "Reply" yourself. # No such attribute would be set for objects of the Message class in that example. def ensure_proper_type: () -> untyped end end module ActiveRecord class InsertAll # :nodoc: attr_reader model: untyped # :nodoc: attr_reader connection: untyped # :nodoc: attr_reader inserts: untyped # :nodoc: attr_reader keys: untyped attr_reader on_duplicate: untyped attr_reader returning: untyped attr_reader unique_by: untyped def initialize: (untyped model, untyped inserts, on_duplicate: untyped on_duplicate, ?unique_by: untyped? unique_by, ?returning: untyped? returning) -> untyped def execute: () -> untyped def updatable_columns: () -> untyped def primary_keys: () -> untyped def skip_duplicates?: () -> untyped def update_duplicates?: () -> untyped def map_key_with_value: () { (untyped, untyped) -> untyped } -> untyped def find_unique_index_for: (untyped unique_by) -> untyped def unique_indexes: () -> untyped def ensure_valid_options_for_connection!: () -> untyped def to_sql: () -> untyped def readonly_columns: () -> untyped def unique_by_columns: () -> untyped def verify_attributes: (untyped attributes) -> untyped class Builder # :nodoc: attr_reader model: untyped def initialize: (untyped insert_all) -> untyped def into: () -> ::String def values_list: () -> untyped def returning: () -> untyped def conflict_target: () -> untyped def updatable_columns: () -> untyped attr_reader connection: untyped attr_reader insert_all: untyped def columns_list: () -> untyped def extract_types_from_columns_on: (untyped table_name, keys: untyped keys) -> untyped def format_columns: (untyped columns) -> untyped def quote_columns: (untyped columns) -> untyped end end end module ActiveRecord module Integration extend ActiveSupport::Concern # 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" def to_param: () -> untyped # 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) def cache_key: () -> untyped # 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+ (which it is by default until Rails 6.0). def cache_version: () -> (nil | untyped) # Returns a cache key along with the version. def cache_key_with_version: () -> untyped module ClassMethods # 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 def to_param: (?untyped? method_name) -> untyped def collection_cache_key: (?untyped collection, ?::Symbol timestamp_column) -> untyped end # Detects if the value before type cast # can be used to generate a cache_version. # # The fast cache version only works with a # string value directly from the database. # # We also must check if the timestamp format has been changed # or if the timezone is not set to UTC then # we cannot apply our transformations correctly. def can_use_fast_cache_version?: (untyped timestamp) -> untyped # Converts a raw database string to `:usec` # format. # # Example: # # timestamp = "2018-10-15 20:02:15.266505" # raw_timestamp_to_cache_version(timestamp) # # => "20181015200215266505" # # PostgreSQL truncates trailing zeros, # https://github.com/postgres/postgres/commit/3e1beda2cde3495f41290e1ece5d544525810214 # to account for this we pad the output with zeros def raw_timestamp_to_cache_version: (untyped timestamp) -> untyped end end module ActiveRecord class InternalMetadata < ActiveRecord::Base def self._internal?: () -> ::TrueClass def self.primary_key: () -> "key" def self.table_name: () -> ::String def self.[]=: (untyped key, untyped value) -> untyped def self.[]: (untyped key) -> untyped def self.table_exists?: () -> untyped # Creates an internal metadata table with columns +key+ and +value+ def self.create_table: () -> untyped def self.drop_table: () -> untyped end end module ActiveRecord module LegacyYamlAdapter def self.convert: (untyped klass, untyped coder) -> untyped module Rails420 def self.convert: (untyped klass, untyped coder) -> untyped end module Rails41 def self.convert: (untyped klass, untyped coder) -> ::Hash[::String, untyped] end end end module ActiveRecord module Locking # == 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 # module Optimistic extend ActiveSupport::Concern def locking_enabled?: () -> untyped def _create_record: (?untyped attribute_names) -> untyped def _touch_row: (untyped attribute_names, untyped time) -> untyped def _update_row: (untyped attribute_names, ?::String attempted_action) -> untyped def destroy_row: () -> untyped module ClassMethods DEFAULT_LOCKING_COLUMN: ::String # 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+). def locking_enabled?: () -> untyped # Set the column to use for optimistic locking. Defaults to +lock_version+. def locking_column=: (untyped value) -> untyped # The version column used for optimistic locking. Defaults to +lock_version+. def locking_column: () -> untyped # Reset the column used for optimistic locking back to the +lock_version+ default. def reset_locking_column: () -> untyped # Make sure the lock version column gets updated when counters are # updated. def update_counters: (untyped id, untyped counters) -> untyped # We need to apply this decorator here, rather than on module inclusion. The closure # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the # sub class being decorated. As such, changes to `lock_optimistically`, or # `locking_column` would not be picked up. def inherited: (untyped subclass) -> untyped end end # Note: It inherits unnamed class, but omitted class LockingType # In de/serialize we change `nil` to 0, so that we can allow passing # `nil` values to `lock_version`, and not result in `ActiveRecord::StaleObjectError` # during update record. # :nodoc: def deserialize: (untyped value) -> untyped def serialize: (untyped value) -> untyped def init_with: (untyped coder) -> untyped def encode_with: (untyped coder) -> untyped end end end module ActiveRecord module Locking # 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: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html # PostgreSQL: https://www.postgresql.org/docs/current/interactive/sql-select.html#SQL-FOR-UPDATE-SHARE module Pessimistic # 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. def lock!: (?bool lock) -> untyped # Wraps the passed block in a transaction, locking the object # before yielding. You can pass the SQL locking clause # as argument (see lock!). def with_lock: (?bool lock) { () -> untyped } -> untyped end end end module ActiveRecord class LogSubscriber < ActiveSupport::LogSubscriber IGNORE_PAYLOAD_NAMES: ::Array[untyped] def self.runtime=: (untyped value) -> untyped def self.runtime: () -> untyped def self.reset_runtime: () -> untyped def sql: (untyped event) -> (nil | untyped) def type_casted_binds: (untyped casted_binds) -> untyped def render_bind: (untyped attr, untyped value) -> ::Array[untyped] def colorize_payload_name: (untyped name, untyped payload_name) -> untyped def sql_color: (untyped sql) -> untyped def logger: () -> untyped def debug: (?untyped? progname) { () -> untyped } -> (nil | untyped) def log_query_source: () -> untyped def extract_query_source_location: (untyped locations) -> untyped end end module ActiveRecord module Middleware # 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 add # the following options to your environment config: # # 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 # # New applications will include these lines commented out in the production.rb. # # 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 class DatabaseSelector def initialize: (untyped app, ?untyped? resolver_klass, ?untyped? context_klass, ?::Hash[untyped, untyped] options) -> untyped attr_reader resolver_klass: untyped attr_reader context_klass: untyped attr_reader options: untyped # Middleware that determines which database connection to use in a multiple # database application. def call: (untyped env) -> untyped def select_database: (untyped request) { () -> untyped } -> untyped def reading_request?: (untyped request) -> untyped end end end module ActiveRecord module Middleware class DatabaseSelector class Resolver # The Resolver class is used by the DatabaseSelector middleware to # determine which database the request should use. # # To change the behavior of the Resolver class in your application, # create a custom resolver class that inherits from # DatabaseSelector::Resolver and implements the methods that need to # be changed. # # By default the Resolver class will send read traffic to the replica # if it's been 2 seconds since the last write. # :nodoc: SEND_TO_REPLICA_DELAY: untyped def self.call: (untyped context, ?::Hash[untyped, untyped] options) -> untyped def initialize: (untyped context, ?::Hash[untyped, untyped] options) -> untyped attr_reader context: untyped attr_reader delay: untyped attr_reader instrumenter: untyped def read: () { () -> untyped } -> untyped def write: () { () -> untyped } -> untyped def read_from_primary: () { () -> untyped } -> untyped def read_from_replica: () { () -> untyped } -> untyped def write_to_primary: () { () -> untyped } -> untyped def read_from_primary?: () -> untyped def send_to_replica_delay: () -> untyped def time_since_last_write_ok?: () -> untyped end end end end module ActiveRecord module Middleware class DatabaseSelector class Resolver class Session # The session class is used by the DatabaseSelector::Resolver to save # timestamps of the last write in the session. # # The last_write is used to determine whether it's safe to read # from the replica or the request needs to be sent to the primary. # :nodoc: def self.call: (untyped request) -> untyped # Converts time to a timestamp that represents milliseconds since # epoch. def self.convert_time_to_timestamp: (untyped time) -> untyped # Converts milliseconds since epoch timestamp into a time object. def self.convert_timestamp_to_time: (untyped timestamp) -> untyped def initialize: (untyped session) -> untyped attr_reader session: untyped def last_write_timestamp: () -> untyped def update_last_write_timestamp: () -> untyped end end end end end module ActiveRecord class Migration # 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_index # * add_reference # * add_timestamps # * change_column # * 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 specify at least one column name or more) # * remove_foreign_key (must supply a second table) # * remove_index # * remove_reference # * remove_timestamps # * rename_column # * rename_index # * rename_table class CommandRecorder ReversibleAndIrreversibleMethods: ::Array[untyped] include JoinTable attr_accessor commands: untyped attr_accessor delegate: untyped attr_accessor reverting: untyped def initialize: (?untyped? delegate) -> untyped # 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]) def revert: () { () -> untyped } -> untyped # Record +command+. +command+ should be a method name and arguments. # For example: # # recorder.record(:method_name, [:arg1, :arg2]) def record: (*untyped command) { () -> untyped } -> untyped # Returns the inverse of the given command. For example: # # recorder.inverse_of(:rename_table, [:old, :new]) # # => [:rename_table, [:new, :old]] # # This method will raise an +IrreversibleMigration+ exception if it cannot # invert the +command+. def inverse_of: (untyped command, untyped args) { () -> untyped } -> untyped def change_table: (untyped table_name, **untyped options) { (untyped) -> untyped } -> untyped def replay: (untyped migration) -> untyped module StraightReversions end include StraightReversions def invert_transaction: (untyped args) { () -> untyped } -> ::Array[:transaction | untyped] def invert_drop_table: (untyped args) { () -> untyped } -> untyped def invert_rename_table: (untyped args) -> ::Array[:rename_table | untyped] def invert_remove_column: (untyped args) -> untyped def invert_rename_index: (untyped args) -> ::Array[:rename_index | untyped] def invert_rename_column: (untyped args) -> ::Array[:rename_column | untyped] def invert_add_index: (untyped args) -> ::Array[:remove_index | ::Array[untyped]] def invert_remove_index: (untyped args) -> untyped def invert_change_column_default: (untyped args) -> ::Array[:change_column_default | ::Array[untyped | { from: untyped, to: untyped }]] def invert_change_column_null: (untyped args) -> ::Array[:change_column_null | untyped] def invert_remove_foreign_key: (untyped args) -> ::Array[:add_foreign_key | untyped] def invert_change_column_comment: (untyped args) -> ::Array[:change_column_comment | ::Array[untyped | { from: untyped, to: untyped }]] def invert_change_table_comment: (untyped args) -> ::Array[:change_table_comment | ::Array[untyped | { from: untyped, to: untyped }]] def respond_to_missing?: (untyped method, untyped _) -> untyped # Forwards any missing method call to the \target. def method_missing: (untyped method, *untyped args) { () -> untyped } -> untyped end end end module ActiveRecord class Migration module Compatibility # :nodoc: all def self.find: (untyped version) -> untyped # workaround: V6_0 and Current are the same object, but RBS doesn't have a syntax for class alias? class V6_0 < Current end class V5_2 < V6_0 module TableDefinition def timestamps: (**untyped options) -> untyped end module CommandRecorder def invert_transaction: (untyped args) { () -> untyped } -> ::Array[:transaction | untyped] def invert_change_column_comment: (untyped args) -> ::Array[:change_column_comment | ::Array[untyped | { from: untyped, to: untyped }]] def invert_change_table_comment: (untyped args) -> ::Array[:change_table_comment | ::Array[untyped | { from: untyped, to: untyped }]] end def create_table: (untyped table_name, **untyped options) { (untyped) -> untyped } -> untyped def change_table: (untyped table_name, **untyped options) { (untyped) -> untyped } -> untyped def create_join_table: (untyped table_1, untyped table_2, **untyped options) { (untyped) -> untyped } -> untyped def add_timestamps: (untyped table_name, **untyped options) -> untyped def compatible_table_definition: (untyped t) -> untyped def command_recorder: () -> untyped end class V5_1 < V5_2 def change_column: (untyped table_name, untyped column_name, untyped `type`, ?::Hash[untyped, untyped] options) -> untyped def create_table: (untyped table_name, **untyped options) -> untyped end class V5_0 < V5_1 module TableDefinition def primary_key: (untyped name, ?::Symbol `type`, **untyped options) -> untyped def references: (*untyped args, **untyped options) -> untyped end def create_table: (untyped table_name, **untyped options) -> untyped def create_join_table: (untyped table_1, untyped table_2, ?column_options: ::Hash[untyped, untyped] column_options, **untyped options) -> untyped def add_column: (untyped table_name, untyped column_name, untyped `type`, **untyped options) -> untyped def add_reference: (untyped table_name, untyped ref_name, **untyped options) -> untyped def compatible_table_definition: (untyped t) -> untyped end class V4_2 < V5_0 module TableDefinition def references: (**untyped options) -> untyped def timestamps: (**untyped options) -> untyped end def add_reference: (untyped table_name, untyped ref_name, **untyped options) -> untyped def add_timestamps: (untyped table_name, **untyped options) -> untyped def index_exists?: (untyped table_name, untyped column_name, ?::Hash[untyped, untyped] options) -> untyped def remove_index: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped def compatible_table_definition: (untyped t) -> untyped def index_name_for_remove: (untyped table_name, ?::Hash[untyped, untyped] options) -> untyped end end end end module ActiveRecord class Migration module JoinTable def find_join_table_name: (untyped table_1, untyped table_2, ?::Hash[untyped, untyped] options) -> untyped def join_table_name: (untyped table_1, untyped table_2) -> untyped end end end module ActiveRecord class MigrationError < ActiveRecordError # nodoc: def initialize: (?untyped? message) -> untyped end # 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[5.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[5.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 # # 2. Use the #reversible method in #change method: # # class ReversibleMigrationExample < ActiveRecord::Migration[5.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 class IrreversibleMigration < MigrationError end class DuplicateMigrationVersionError < MigrationError # nodoc: def initialize: (?untyped? version) -> untyped end class DuplicateMigrationNameError < MigrationError # nodoc: def initialize: (?untyped? name) -> untyped end class UnknownMigrationVersionError < MigrationError # nodoc: def initialize: (?untyped? version) -> untyped end class IllegalMigrationNameError < MigrationError # nodoc: def initialize: (?untyped? name) -> untyped end class PendingMigrationError < MigrationError # nodoc: include ActiveSupport::ActionableError extend ::ActiveSupport::ActionableError::ClassMethods def initialize: (?untyped? message) -> untyped end class ConcurrentMigrationError < MigrationError # nodoc: DEFAULT_MESSAGE: ::String RELEASE_LOCK_FAILED_MESSAGE: ::String def initialize: (?untyped message) -> untyped end class NoEnvironmentInSchemaError < MigrationError # nodoc: def initialize: () -> untyped end class ProtectedEnvironmentError < ActiveRecordError # nodoc: def initialize: (?::String env) -> untyped end class EnvironmentMismatchError < ActiveRecordError def initialize: (?stored: untyped? stored, ?current: untyped? current) -> untyped end # = 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[5.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[5.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 # 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. # # 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[5.0] # def change # add_column :tablenames, :fieldname, :string # end # end # # To run migrations against the currently configured database, use # 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 # 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. 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. # # == Database support # # Migrations are currently supported in MySQL, PostgreSQL, SQLite, # SQL Server, and Oracle (all supported databases except DB2). # # == More examples # # Not all migrations change the schema. Some just fix the data: # # class RemoveEmptyTags < ActiveRecord::Migration[5.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[5.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[5.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[5.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[5.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[5.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!. class Migration class Current < Migration end def self.inherited: (untyped subclass) -> untyped def self.[]: (untyped version) -> untyped def self.current_version: () -> untyped MigrationFilenameRegexp: untyped # 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 class CheckPending def initialize: (untyped app) -> untyped def call: (untyped env) -> untyped def connection: () -> untyped end attr_accessor delegate: untyped attr_accessor disable_ddl_transaction: untyped def self.nearest_delegate: () -> untyped # Raises ActiveRecord::PendingMigrationError error if any migrations are pending. def self.check_pending!: (?untyped connection) -> untyped def self.load_schema_if_pending!: () -> untyped def self.maintain_test_schema!: () -> untyped def self.method_missing: (untyped name, *untyped args) { () -> untyped } -> untyped def self.migrate: (untyped direction) -> untyped # 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}[rdoc-ref:Migration]. def self.disable_ddl_transaction!: () -> untyped def disable_ddl_transaction: () -> untyped attr_accessor name: untyped attr_accessor version: untyped def initialize: (?untyped name, ?untyped? version) -> untyped # 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[5.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[5.0] # def change # revert TenderloveMigration # # create_table(:apples) do |t| # t.string :variety # end # end # end # # This command can be nested. def revert: (*untyped migration_classes) { () -> untyped } -> untyped def reverting?: () -> untyped class ReversibleBlockHelper < ::Struct[untyped] attr_accessor reverting(): untyped # nodoc: def up: () { () -> untyped } -> untyped def down: () { () -> untyped } -> untyped end # 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[5.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 def reversible: () { (untyped) -> untyped } -> untyped # 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[5.2] # def change # add_column :posts, :published, :boolean, default: false # up_only do # execute "update posts set published = 'true'" # end # end # end def up_only: () { () -> untyped } -> untyped # Runs the given migration classes. # Last argument can specify options: # - :direction (default is :up) # - :revert (default is false) def run: (*untyped migration_classes) -> untyped def up: () -> (nil | untyped) def down: () -> (nil | untyped) # Execute this migration in the named direction def migrate: (untyped direction) -> (nil | untyped) def exec_migration: (untyped conn, untyped direction) -> untyped def write: (?::String text) -> untyped def announce: (untyped message) -> untyped # Takes a message argument and outputs it as is. # A second boolean argument can be passed to specify whether to indent or not. def say: (untyped message, ?bool subitem) -> untyped # 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. def say_with_time: (untyped message) { () -> untyped } -> untyped # Takes a block as an argument and suppresses any output generated by the block. def suppress_messages: () { () -> untyped } -> untyped def connection: () -> untyped def method_missing: (untyped method, *untyped arguments) { () -> untyped } -> untyped def copy: (untyped destination, untyped sources, ?::Hash[untyped, untyped] options) -> untyped # 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. def proper_table_name: (untyped name, ?::Hash[untyped, untyped] options) -> untyped # Determines the version number of the next migration. def next_migration_number: (untyped number) -> untyped def table_name_options: (?untyped config) -> { table_name_prefix: untyped, table_name_suffix: untyped } def execute_block: () { () -> untyped } -> untyped def command_recorder: () -> CommandRecorder end # MigrationProxy is used to defer loading of the actual migration classes # until they are needed class MigrationProxy < ::Struct[untyped] attr_accessor name(): untyped attr_accessor version(): untyped attr_accessor filename(): untyped attr_accessor scope(): untyped def initialize: (untyped name, untyped version, untyped filename, untyped scope) -> untyped def basename: () -> untyped def mtime: () -> untyped def migration: () -> untyped def load_migration: () -> untyped end class NullMigration < MigrationProxy # nodoc: def initialize: () -> untyped def mtime: () -> 0 end class MigrationContext # nodoc: attr_reader migrations_paths: untyped # nodoc: attr_reader schema_migration: untyped def initialize: (untyped migrations_paths, untyped schema_migration) -> untyped def migrate: (?untyped? target_version) { () -> untyped } -> untyped def rollback: (?::Integer steps) -> untyped def forward: (?::Integer steps) -> untyped def up: (?untyped? target_version) { (untyped) -> untyped } -> untyped def down: (?untyped? target_version) { (untyped) -> untyped } -> untyped def run: (untyped direction, untyped target_version) -> untyped def open: () -> Migrator def get_all_versions: () -> untyped def current_version: () -> untyped def needs_migration?: () -> untyped def any_migrations?: () -> untyped def last_migration: () -> untyped def migrations: () -> untyped def migrations_status: () -> untyped def current_environment: () -> untyped def protected_environment?: () -> untyped def last_stored_environment: () -> (nil | untyped) def migration_files: () -> untyped def parse_migration_filename: (untyped filename) -> untyped def move: (untyped direction, untyped steps) -> untyped end class Migrator attr_accessor migrations_paths: untyped # For cases where a table doesn't exist like loading from schema cache def self.current_version: () -> untyped def initialize: (untyped direction, untyped migrations, untyped schema_migration, ?untyped? target_version) -> untyped def current_version: () -> untyped def current_migration: () -> untyped def run: () -> untyped def migrate: () -> untyped def runnable: () -> untyped def migrations: () -> untyped def pending_migrations: () -> untyped def migrated: () -> untyped def load_migrated: () -> untyped # Used for running a specific migration. def run_without_lock: () -> untyped # Used for running multiple migrations up to or down to a certain value. def migrate_without_lock: () -> untyped # Stores the current environment in the database. def record_environment: () -> (nil | untyped) def ran?: (untyped migration) -> untyped # Return true if a valid version is not provided. def invalid_target?: () -> untyped def execute_migration_in_transaction: (untyped migration, untyped direction) -> untyped def target: () -> untyped def finish: () -> untyped def start: () -> untyped def validate: (untyped migrations) -> untyped def record_version_state_after_migrating: (untyped version) -> untyped def up?: () -> untyped def down?: () -> untyped # Wrap the migration in a transaction only if supported by the adapter. def ddl_transaction: (untyped migration) { () -> untyped } -> untyped def use_transaction?: (untyped migration) -> untyped def use_advisory_lock?: () -> untyped def with_advisory_lock: () { () -> untyped } -> untyped MIGRATOR_SALT: ::Integer def generate_migrator_advisory_lock_id: () -> untyped end end module ActiveRecord module ModelSchema extend ActiveSupport::Concern def self.derive_join_table_name: (untyped first_table, untyped second_table) -> untyped module ClassMethods # 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". # # You can also set your own table name explicitly: # # class Mouse < ActiveRecord::Base # self.table_name = "mice" # end def table_name: () -> untyped # Sets the table name explicitly. Example: # # class Project < ActiveRecord::Base # self.table_name = "project" # end def table_name=: (untyped value) -> (nil | untyped) # Returns a quoted version of the table name, used to construct SQL statements. def quoted_table_name: () -> untyped def reset_table_name: () -> untyped def full_table_name_prefix: () -> untyped def full_table_name_suffix: () -> untyped # The array of names of environments where destructive actions should be prohibited. By default, # the value is ["production"]. def protected_environments: () -> untyped # Sets an array of names of environments where destructive actions should be prohibited. def protected_environments=: (untyped environments) -> untyped # Defines the name of the table column which will store 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' def inheritance_column: () -> untyped # Sets the value of inheritance_column def inheritance_column=: (untyped value) -> untyped # 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. def ignored_columns: () -> untyped # Sets the columns names the model should ignore. Ignored columns won't have attribute # accessors defined, and won't be referenced in SQL queries. def ignored_columns=: (untyped columns) -> untyped def sequence_name: () -> untyped def reset_sequence_name: () -> untyped # 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 def sequence_name=: (untyped value) -> untyped # Determines if the primary key values should be selected from their # corresponding sequence before the insert statement. def prefetch_primary_key?: () -> untyped # Returns the next value that will be used as the primary key on # an insert statement. def next_sequence_value: () -> untyped # Indicates whether the table associated with this class exists def table_exists?: () -> untyped def attributes_builder: () -> untyped def columns_hash: () -> untyped def columns: () -> untyped def attribute_types: () -> untyped def yaml_encoder: () -> untyped # 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. def type_for_attribute: (untyped attr_name) { () -> untyped } -> untyped # Returns a hash where the keys are column names and the values are # default values when instantiating the Active Record object for this table. def column_defaults: () -> untyped def _default_attributes: () -> untyped # Returns an array of column names as strings. def column_names: () -> untyped def symbol_column_to_string: (untyped name_symbol) -> untyped # 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. def content_columns: () -> untyped # 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, eg: # # class CreateJobLevels < ActiveRecord::Migration[5.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 def reset_column_information: () -> untyped def initialize_load_schema_monitor: () -> untyped def inherited: (untyped child_class) -> untyped def schema_loaded?: () -> untyped def load_schema: () -> (nil | untyped) def load_schema!: () -> untyped def reload_schema_from_cache: () -> untyped # Guesses the table name, but does not decorate it with prefix and suffix information. def undecorated_table_name: (?untyped class_name) -> untyped # Computes and returns a table name according to default conventions. def compute_table_name: () -> untyped end end end module ActiveRecord module NestedAttributes # nodoc: class TooManyRecords < ActiveRecordError end extend ActiveSupport::Concern # = 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 # # If you want to validate that a child record is associated with a parent # record, you can use the +validates_presence_of+ method and the +:inverse_of+ # key as this example illustrates: # # class Member < ActiveRecord::Base # has_many :posts, inverse_of: :member # accepts_nested_attributes_for :posts # end # # class Post < ActiveRecord::Base # belongs_to :member, inverse_of: :posts # validates_presence_of :member # 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 module ClassMethods REJECT_ALL_BLANK_PROC: untyped # 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+ # (eg. 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 def accepts_nested_attributes_for: (*untyped attr_names) -> untyped # Generates a writer method for this association. Serves as a point for # accessing the objects in the association. For example, this method # could generate the following: # # def pirate_attributes=(attributes) # assign_nested_attributes_for_one_to_one_association(:pirate, attributes) # end # # This redirects the attempts to write objects in an association through # the helper methods defined below. Makes it seem like the nested # associations are just regular associations. def generate_association_writer: (untyped association_name, untyped `type`) -> untyped end # Returns ActiveRecord::AutosaveAssociation::marked_for_destruction? It's # used in conjunction with fields_for to build a form element for the # destruction of this association. # # See ActionView::Helpers::FormHelper::fields_for for more info. def _destroy: () -> untyped # Attribute hash keys that should not be assigned as normal attributes. # These hash keys are nested attributes implementation details. UNASSIGNABLE_KEYS: ::Array[untyped] # Assigns the given attributes to the association. # # If an associated record does not yet exist, one will be instantiated. If # an associated record already exists, the method's behavior depends on # the value of the update_only option. If update_only is +false+ and the # given attributes include an :id that matches the existing record's # id, then the existing record will be modified. If no :id is provided # it will be replaced with a new record. If update_only is +true+ the existing # record will be modified regardless of whether an :id is provided. # # If the given attributes include a matching :id attribute, or # update_only is true, and a :_destroy key set to a truthy value, # then the existing record will be marked for destruction. def assign_nested_attributes_for_one_to_one_association: (untyped association_name, untyped attributes) -> untyped # Assigns the given attributes to the collection association. # # Hashes with an :id value matching an existing associated record # will update that record. Hashes without an :id value will build # a new record for the association. Hashes with a matching :id # value and a :_destroy key set to a truthy value will mark the # matched record for destruction. # # For example: # # assign_nested_attributes_for_collection_association(:people, { # '1' => { id: '1', name: 'Peter' }, # '2' => { name: 'John' }, # '3' => { id: '2', _destroy: true } # }) # # Will update the name of the Person with ID 1, build a new associated # person with the name 'John', and mark the associated Person with ID 2 # for destruction. # # Also accepts an Array of attribute hashes: # # assign_nested_attributes_for_collection_association(:people, [ # { id: '1', name: 'Peter' }, # { name: 'John' }, # { id: '2', _destroy: true } # ]) def assign_nested_attributes_for_collection_association: (untyped association_name, untyped attributes_collection) -> untyped # Takes in a limit and checks if the attributes_collection has too many # records. It accepts limit in the form of symbol, proc, or # number-like object (anything that can be compared with an integer). # # Raises TooManyRecords error if the attributes_collection is # larger than the limit. def check_record_limit!: (untyped limit, untyped attributes_collection) -> untyped # Updates a record with the +attributes+ or marks it for destruction if # +allow_destroy+ is +true+ and has_destroy_flag? returns +true+. def assign_to_or_mark_for_destruction: (untyped record, untyped attributes, untyped allow_destroy) -> untyped # Determines if a hash contains a truthy _destroy key. def has_destroy_flag?: (untyped hash) -> untyped # Determines if a new record should be rejected by checking # has_destroy_flag? or if a :reject_if proc exists for this # association and evaluates to +true+. def reject_new_record?: (untyped association_name, untyped attributes) -> untyped # Determines if a record with the particular +attributes+ should be # rejected by calling the reject_if Symbol or Proc (if defined). # The reject_if option is defined by +accepts_nested_attributes_for+. # # Returns false if there is a +destroy_flag+ on the attributes. def call_reject_if: (untyped association_name, untyped attributes) -> (::FalseClass | untyped) # Only take into account the destroy flag if :allow_destroy is true def will_be_destroyed?: (untyped association_name, untyped attributes) -> untyped def allow_destroy?: (untyped association_name) -> untyped def raise_nested_attributes_record_not_found!: (untyped association_name, untyped record_id) -> untyped end end module ActiveRecord # = Active Record No Touching module NoTouching extend ActiveSupport::Concern module ClassMethods # 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 # def no_touching: () { () -> untyped } -> untyped end def self.apply_to: (untyped klass) { () -> untyped } -> untyped def self.applied_to?: (untyped klass) -> untyped def self.klasses: () -> untyped # 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 # def no_touching?: () -> untyped def touch_later: () -> untyped def touch: () -> untyped end end module ActiveRecord module NullRelation # :nodoc: def pluck: (*untyped column_names) -> ::Array[untyped] def delete_all: () -> 0 def update_all: (untyped _updates) -> 0 def delete: (untyped _id_or_array) -> 0 def empty?: () -> ::TrueClass def none?: () -> ::TrueClass def any?: () -> ::FalseClass def one?: () -> ::FalseClass def many?: () -> ::FalseClass def to_sql: () -> ::String def calculate: (untyped operation, untyped _column_name) -> untyped def exists?: (?::Symbol _conditions) -> ::FalseClass def or: (untyped other) -> untyped def exec_queries: () -> untyped end end module ActiveRecord # = Active Record \Persistence module Persistence extend ActiveSupport::Concern module ClassMethods # 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 def create: (?untyped? attributes) { () -> untyped } -> untyped # 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. def create!: (?untyped? attributes) { () -> untyped } -> untyped # 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 ActiveRecord::Persistence#insert_all for documentation. def insert: (untyped attributes, ?unique_by: untyped? unique_by, ?returning: untyped? returning) -> untyped # 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. # # [: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. # # ==== 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" } # ]) def insert_all: (untyped attributes, ?unique_by: untyped? unique_by, ?returning: untyped? returning) -> untyped # 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 ActiveRecord::Persistence#insert_all! for more. def insert!: (untyped attributes, ?returning: untyped? returning) -> untyped # 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 ActiveRecord::Persistence#insert_all. # To replace them, see ActiveRecord::Persistence#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. # # ==== 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" } # ]) def insert_all!: (untyped attributes, ?returning: untyped? returning) -> untyped # 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 ActiveRecord::Persistence#upsert_all for documentation. def upsert: (untyped attributes, ?unique_by: untyped? unique_by, ?returning: untyped? returning) -> untyped # 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). # # ==== 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. # # [: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. # # ==== 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" def upsert_all: (untyped attributes, ?unique_by: untyped? unique_by, ?returning: untyped? returning) -> untyped # 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. def instantiate: (untyped attributes, ?::Hash[untyped, untyped] column_types) { () -> untyped } -> untyped # 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. # * +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}[rdoc-ref:Relation#update_all] # for updating all records in a single query. def update: (?::Symbol id, untyped attributes) -> untyped # 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) def destroy: (untyped id) -> untyped # 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]) def delete: (untyped id_or_array) -> untyped def _insert_record: (untyped values) -> untyped def _update_record: (untyped values, untyped constraints) -> untyped def _delete_record: (untyped constraints) -> untyped # Given a class, an attributes hash, +instantiate_instance_of+ returns a # new instance of the class. Accepts only keys as strings. def instantiate_instance_of: (untyped klass, untyped attributes, ?::Hash[untyped, untyped] column_types) { () -> untyped } -> untyped # Called by +instantiate+ to decide which class to use for a new # record instance. # # See +ActiveRecord::Inheritance#discriminate_class_for_record+ for # the single-table inheritance discriminator. def discriminate_class_for_record: (untyped record) -> untyped def _substitute_values: (untyped values) -> untyped end # 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. def new_record?: () -> untyped # Returns true if this object has been destroyed, otherwise returns false. def destroyed?: () -> untyped # Returns true if the record is persisted, i.e. it's not a new record and it was # not destroyed, otherwise returns false. def persisted?: () -> untyped # # :call-seq: # save(*args) # # 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. def save: (*untyped args, **untyped options) { () -> untyped } -> untyped # # :call-seq: # save!(*args) # # 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. def save!: (*untyped args, **untyped options) { () -> untyped } -> untyped # 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?}[rdoc-ref:Core#readonly?]. # # To enforce the object's +before_destroy+ and +after_destroy+ # callbacks or any :dependent association # options, use #destroy. def delete: () -> untyped # 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. def destroy: () -> untyped # 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. def destroy!: () -> untyped # Returns an instance of the specified +klass+ with the attributes of the # current record. This is mostly useful in relation to single-table # inheritance 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. def becomes: (untyped klass) -> untyped # 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. def becomes!: (untyped klass) -> untyped # 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. def update_attribute: (untyped name, untyped value) -> untyped # 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. def update: (untyped attributes) -> untyped # 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. def update!: (untyped attributes) -> untyped # Equivalent to update_columns(name => value). def update_column: (untyped name, untyped value) -> untyped # 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. def update_columns: (untyped attributes) -> untyped # 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+. def increment: (untyped attribute, ?::Integer by) -> untyped # 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+. def increment!: (untyped attribute, ?::Integer by, ?touch: untyped? touch) -> untyped # 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+. def decrement: (untyped attribute, ?::Integer by) -> untyped # 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+. def decrement!: (untyped attribute, ?::Integer by, ?touch: untyped? touch) -> untyped # 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 # def toggle: (untyped attribute) -> untyped # 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. def toggle!: (untyped attribute) -> untyped # 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 = 1 # account.reload # # Account Load (1.2ms) SELECT "accounts".* FROM "accounts" WHERE "accounts"."id" = $1 LIMIT 1 [["id", 1]] # # => # # # 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 # def reload: (?untyped? options) -> untyped # 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}[rdoc-ref:Associations::ClassMethods#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 # def touch: (*untyped names, ?time: untyped? time) -> untyped # A hook to be overridden by association modules. def destroy_associations: () -> nil def destroy_row: () -> untyped def _delete_row: () -> untyped def _touch_row: (untyped attribute_names, untyped time) -> untyped def _update_row: (untyped attribute_names, ?::String attempted_action) -> untyped def create_or_update: () { () -> untyped } -> (::FalseClass | untyped) # Updates the associated record with values matching those of the instance attributes. # Returns the number of affected rows. def _update_record: (?untyped attribute_names) { (untyped) -> untyped } -> untyped # Creates a record with values matching those of the instance attributes # and returns its id. def _create_record: (?untyped attribute_names) { (untyped) -> untyped } -> untyped def verify_readonly_attribute: (untyped name) -> untyped def _raise_record_not_destroyed: () -> untyped # The name of the method used to touch a +belongs_to+ association when the # +:touch+ option is used. def belongs_to_touch_method: () -> :touch def _raise_readonly_record_error: () -> untyped end end module ActiveRecord # = Active Record Query Cache class QueryCache module ClassMethods # Enable the query cache within the block if Active Record is configured. # If it's not, it will execute the given block. def cache: () { () -> untyped } -> untyped # Disable the query cache within the block if Active Record is configured. # If it's not, it will execute the given block. def uncached: () { () -> untyped } -> untyped end def self.run: () -> untyped def self.complete: (untyped pools) -> untyped def self.install_executor_hooks: (?untyped executor) -> untyped end end module ActiveRecord module Querying QUERYING_METHODS: untyped # 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" # # => [#"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 }] def find_by_sql: (untyped sql, ?untyped binds, ?preparable: untyped? preparable) { () -> untyped } -> untyped # 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. def count_by_sql: (untyped sql) -> untyped end end module ActiveRecord class Railtie < Rails::Railtie include ActiveRecord::Railties::ControllerRuntime extend ::ActiveRecord::Railties::ControllerRuntime::ClassMethods end end module ActiveRecord module Railties module CollectionCacheAssociationLoading # :nodoc: # nodoc: def setup: (untyped context, untyped options, untyped as, untyped block) -> untyped def relation_from_options: (?collection: untyped? collection, ?partial: untyped? partial, ?cached: untyped? cached, **untyped _) -> (nil | untyped) def collection_without_template: () -> untyped def collection_with_template: () -> untyped end end end module ActiveRecord module Railties module ControllerRuntime # :nodoc: # nodoc: extend ActiveSupport::Concern module ClassMethods # :nodoc: def log_process_action: (untyped payload) -> untyped end def process_action: (untyped action, *untyped args) -> untyped def cleanup_view_runtime: () -> untyped def append_info_to_payload: (untyped payload) -> untyped end end end module ActiveRecord extend ActiveSupport::Autoload module Coders end module AttributeMethods extend ActiveSupport::Autoload end module Locking extend ActiveSupport::Autoload end module ConnectionAdapters extend ActiveSupport::Autoload end module Scoping extend ::ActiveRecord::Scoping::Named::ClassMethods extend ::ActiveRecord::Scoping::Default::ClassMethods extend ActiveSupport::Autoload end module Middleware extend ActiveSupport::Autoload end module Tasks extend ActiveSupport::Autoload end def self.eager_load!: () -> untyped end module ActiveRecord module ReadonlyAttributes extend ActiveSupport::Concern module ClassMethods # Attributes listed as readonly will be used to create a new record but update operations will # ignore these fields. def attr_readonly: (*untyped attributes) -> untyped # Returns an array of all the attributes that have been specified as readonly. def readonly_attributes: () -> untyped end end end module ActiveRecord module Reflection # = Active Record Reflection # :nodoc: extend ActiveSupport::Concern def self.create: (untyped macro, untyped name, untyped scope, untyped options, untyped ar) -> untyped def self.add_reflection: (untyped ar, untyped name, untyped reflection) -> untyped def self.add_aggregate_reflection: (untyped ar, untyped name, untyped reflection) -> untyped def self.reflection_class_for: (untyped macro) -> untyped # \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. module ClassMethods # Returns an array of AggregateReflection objects for all the aggregations in the class. def reflect_on_all_aggregations: () -> untyped # Returns the AggregateReflection object for the named +aggregation+ (use the symbol). # # Account.reflect_on_aggregation(:balance) # => the balance AggregateReflection # def reflect_on_aggregation: (untyped aggregation) -> untyped # Returns a Hash of name of the reflection as the key and an AssociationReflection as the value. # # Account.reflections # => {"balance" => AggregateReflection} # def reflections: () -> untyped # 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 # def reflect_on_all_associations: (?untyped? macro) -> untyped # 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 # def reflect_on_association: (untyped association) -> untyped def _reflect_on_association: (untyped association) -> untyped # Returns an array of AssociationReflection objects for all associations which have :autosave enabled. def reflect_on_all_autosave_associations: () -> untyped def clear_reflections_cache: () -> untyped end class AbstractReflection # Holds all the methods that are shared between MacroReflection and ThroughReflection. # # AbstractReflection # MacroReflection # AggregateReflection # AssociationReflection # HasManyReflection # HasOneReflection # BelongsToReflection # HasAndBelongsToManyReflection # ThroughReflection # PolymorphicReflection # RuntimeReflection # :nodoc: def through_reflection?: () -> ::FalseClass def table_name: () -> untyped # Returns a new, unsaved instance of the associated class. +attributes+ will # be passed to the class's constructor. def build_association: (untyped attributes) { () -> untyped } -> untyped # Returns the class name for the macro. # # composed_of :balance, class_name: 'Money' returns 'Money' # has_many :clients returns 'Client' def class_name: () -> untyped class JoinKeys < ::Struct[untyped] attr_accessor key(): untyped attr_accessor foreign_key(): untyped end def join_keys: () -> untyped # Returns a list of scopes that should be applied for this Reflection # object when querying the database. def scopes: () -> untyped def join_scope: (untyped table, untyped foreign_table, untyped foreign_klass) -> untyped def join_scopes: (untyped table, untyped predicate_builder) -> untyped def klass_join_scope: (untyped table, untyped predicate_builder) -> untyped def constraints: () -> untyped def counter_cache_column: () -> untyped def inverse_of: () -> (nil | untyped) def check_validity_of_inverse!: () -> untyped # This shit is nasty. We need to avoid the following situation: # # * An associated record is deleted via record.destroy # * Hence the callbacks run, and they find a belongs_to on the record with a # :counter_cache options which points back at our owner. So they update the # counter cache. # * In which case, we must make sure to *not* update the counter cache, or else # it will be decremented twice. # # Hence this method. def inverse_which_updates_counter_cache: () -> untyped def inverse_updates_counter_in_memory?: () -> untyped # Returns whether a counter cache should be used for this association. # # The counter_cache option must be given on either the owner or inverse # association, and the column must be present on the owner. def has_cached_counter?: () -> untyped def counter_must_be_updated_by_has_many?: () -> untyped def alias_candidate: (untyped name) -> ::String def chain: () -> untyped def get_join_keys: (untyped association_klass) -> JoinKeys def build_scope: (untyped table, ?untyped predicate_builder) -> untyped def join_primary_key: () -> untyped def join_foreign_key: () -> untyped def actual_source_reflection: () -> untyped def predicate_builder: (untyped table) -> PredicateBuilder def primary_key: (untyped klass) -> untyped end # Base class for AggregateReflection and AssociationReflection. Objects of # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. class MacroReflection < AbstractReflection # Returns the name of the macro. # # composed_of :balance, class_name: 'Money' returns :balance # has_many :clients returns :clients attr_reader name: untyped attr_reader scope: untyped # Returns the hash of options used for the macro. # # composed_of :balance, class_name: 'Money' returns { class_name: "Money" } # has_many :clients returns {} attr_reader options: untyped attr_reader active_record: untyped attr_reader plural_name: untyped def initialize: (untyped name, untyped scope, untyped options, untyped active_record) -> untyped def autosave=: (untyped autosave) -> untyped # 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. def klass: () -> untyped def compute_class: (untyped name) -> untyped # 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. def ==: (untyped other_aggregation) -> untyped def scope_for: (untyped relation, ?untyped? owner) -> untyped def derive_class_name: () -> untyped end class AggregateReflection < MacroReflection # Holds all the metadata about an aggregation as it was specified in the # Active Record class. # nodoc: def mapping: () -> untyped end class AssociationReflection < MacroReflection # Holds all the metadata about an association as it was specified in the # Active Record class. # nodoc: def compute_class: (untyped name) -> untyped attr_reader type: untyped attr_reader foreign_type: untyped attr_accessor parent_reflection: untyped def initialize: (untyped name, untyped scope, untyped options, untyped active_record) -> untyped def association_scope_cache: (untyped conn, untyped owner) { () -> untyped } -> untyped def constructable?: () -> untyped def join_table: () -> untyped def foreign_key: () -> untyped def association_foreign_key: () -> untyped # klass option is necessary to support loading polymorphic associations def association_primary_key: (?untyped? klass) -> untyped def active_record_primary_key: () -> untyped def check_validity!: () -> untyped def check_preloadable!: () -> (nil | untyped) def join_id_for: (untyped owner) -> untyped def through_reflection: () -> nil def source_reflection: () -> untyped # A chain of reflections from this one back to the owner. For more see the explanation in # ThroughReflection. def collect_join_chain: () -> ::Array[untyped] def clear_association_scope_cache: () -> untyped def nested?: () -> ::FalseClass def has_scope?: () -> untyped def has_inverse?: () -> untyped def polymorphic_inverse_of: (untyped associated_class) -> untyped # Returns the macro type. # # has_many :clients returns :has_many def macro: () -> untyped # Returns whether or not this association reflection is for a collection # association. Returns +true+ if the +macro+ is either +has_many+ or # +has_and_belongs_to_many+, +false+ otherwise. def collection?: () -> ::FalseClass # Returns whether or not the association should be validated as part of # the parent's validation. # # Unless you explicitly disable validation with # validate: false, validation will take place when: # # * you explicitly enable validation; validate: true # * you use autosave; autosave: true # * the association is a +has_many+ association def validate?: () -> untyped # Returns +true+ if +self+ is a +belongs_to+ reflection. def belongs_to?: () -> ::FalseClass # Returns +true+ if +self+ is a +has_one+ reflection. def has_one?: () -> ::FalseClass def association_class: () -> untyped def polymorphic?: () -> untyped VALID_AUTOMATIC_INVERSE_MACROS: ::Array[untyped] INVALID_AUTOMATIC_INVERSE_OPTIONS: ::Array[untyped] def add_as_source: (untyped seed) -> untyped def add_as_polymorphic_through: (untyped reflection, untyped seed) -> untyped def add_as_through: (untyped seed) -> untyped def extensions: () -> untyped def calculate_constructable: (untyped macro, untyped options) -> ::TrueClass # Attempts to find the inverse association name automatically. # If it cannot find a suitable inverse association name, it returns # +nil+. def inverse_name: () -> untyped # returns either +nil+ or the inverse association name that it finds. def automatic_inverse_of: () -> untyped # Checks if the inverse reflection that is returned from the # +automatic_inverse_of+ method is a valid reflection. We must # make sure that the reflection's active_record name matches up # with the current reflection's klass name. def valid_inverse_reflection?: (untyped reflection) -> untyped # Checks to see if the reflection doesn't have any options that prevent # us from being able to guess the inverse automatically. First, the # inverse_of option cannot be set to false. Second, we must # have has_many, has_one, belongs_to associations. # Third, we must not have options such as :foreign_key # which prevent us from correctly guessing the inverse association. # # Anything with a scope can additionally ruin our attempt at finding an # inverse, so we exclude reflections with scopes. def can_find_inverse_of_automatically?: (untyped reflection) -> untyped def derive_class_name: () -> untyped def derive_foreign_key: () -> untyped def derive_join_table: () -> untyped end class HasManyReflection < AssociationReflection # :nodoc: def macro: () -> :has_many def collection?: () -> ::TrueClass def association_class: () -> untyped def association_primary_key: (?untyped? klass) -> untyped end class HasOneReflection < AssociationReflection # :nodoc: def macro: () -> :has_one def has_one?: () -> ::TrueClass def association_class: () -> untyped def calculate_constructable: (untyped macro, untyped options) -> untyped end class BelongsToReflection < AssociationReflection # :nodoc: def macro: () -> :belongs_to def belongs_to?: () -> ::TrueClass def association_class: () -> untyped def join_primary_key: (?untyped? klass) -> untyped def join_foreign_key: () -> untyped def can_find_inverse_of_automatically?: (untyped _) -> untyped def calculate_constructable: (untyped macro, untyped options) -> untyped end class HasAndBelongsToManyReflection < AssociationReflection # :nodoc: def macro: () -> :has_and_belongs_to_many def collection?: () -> ::TrueClass end class ThroughReflection < AbstractReflection def initialize: (untyped delegate_reflection) -> untyped def through_reflection?: () -> ::TrueClass def klass: () -> untyped # Returns the source of the through reflection. It checks both a singularized # and pluralized form for :belongs_to or :has_many. # # class Post < ActiveRecord::Base # has_many :taggings # has_many :tags, through: :taggings # end # # class Tagging < ActiveRecord::Base # belongs_to :post # belongs_to :tag # end # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.source_reflection # # => # def source_reflection: () -> untyped # Returns the AssociationReflection object specified in the :through option # of a HasManyThrough or HasOneThrough association. # # class Post < ActiveRecord::Base # has_many :taggings # has_many :tags, through: :taggings # end # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.through_reflection # # => # def through_reflection: () -> untyped # Returns an array of reflections which are involved in this association. Each item in the # array corresponds to a table which will be part of the query for this association. # # The chain is built by recursively calling #chain on the source reflection and the through # reflection. The base case for the recursion is a normal association, which just returns # [self] as its #chain. # # class Post < ActiveRecord::Base # has_many :taggings # has_many :tags, through: :taggings # end # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.chain # # => [, # ] # def collect_join_chain: () -> untyped def clear_association_scope_cache: () -> untyped def scopes: () -> untyped def join_scopes: (untyped table, untyped predicate_builder) -> untyped def has_scope?: () -> untyped # A through association is nested if there would be more than one join table def nested?: () -> untyped # We want to use the klass from this reflection, rather than just delegate straight to # the source_reflection, because the source_reflection may be polymorphic. We still # need to respect the source_reflection's :primary_key option, though. def association_primary_key: (?untyped? klass) -> untyped # Gets an array of possible :through source reflection names in both singular and plural form. # # class Post < ActiveRecord::Base # has_many :taggings # has_many :tags, through: :taggings # end # # tags_reflection = Post.reflect_on_association(:tags) # tags_reflection.source_reflection_names # # => [:tag, :tags] # def source_reflection_names: () -> untyped def source_reflection_name: () -> untyped def source_options: () -> untyped def through_options: () -> untyped def check_validity!: () -> untyped def constraints: () -> untyped def add_as_source: (untyped seed) -> untyped def add_as_polymorphic_through: (untyped reflection, untyped seed) -> untyped def add_as_through: (untyped seed) -> untyped def actual_source_reflection: () -> untyped attr_reader delegate_reflection: untyped def collect_join_reflections: (untyped seed) -> untyped def inverse_name: () -> untyped def derive_class_name: () -> untyped end class PolymorphicReflection < AbstractReflection def initialize: (untyped reflection, untyped previous_reflection) -> untyped def join_scopes: (untyped table, untyped predicate_builder) -> untyped def constraints: () -> untyped def source_type_scope: () -> untyped end class RuntimeReflection < AbstractReflection def initialize: (untyped reflection, untyped association) -> untyped def klass: () -> untyped def aliased_table: () -> untyped def all_includes: () { () -> untyped } -> untyped end end end module ActiveRecord module Batches class BatchEnumerator include Enumerable[untyped, untyped] def initialize: (relation: untyped relation, ?finish: untyped? finish, ?start: untyped? start, ?of: ::Integer of) -> untyped # 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 def each_record: () { (untyped) -> untyped } -> untyped # Yields an ActiveRecord::Relation object for each batch of records. # # Person.in_batches.each do |relation| # relation.update_all(awesome: true) # end def each: () { (untyped) -> untyped } -> untyped end end end module ActiveRecord module Batches ORDER_IGNORE_MESSAGE: ::String # 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. # # 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: It's not possible to set the order. That is automatically set to # ascending on the primary key ("id ASC") to make the batch ordering # work. 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. def find_each: (?error_on_ignore: untyped? error_on_ignore, ?batch_size: ::Integer batch_size, ?finish: untyped? finish, ?start: untyped? start) { (untyped) -> untyped } -> untyped # 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. # # 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: It's not possible to set the order. That is automatically set to # ascending on the primary key ("id ASC") to make the batch ordering # work. 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. def find_in_batches: (?error_on_ignore: untyped? error_on_ignore, ?batch_size: ::Integer batch_size, ?finish: untyped? finish, ?start: untyped? start) { (untyped) -> untyped } -> untyped # 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. # # 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: It's not possible to set the order. That is automatically set to # ascending on the primary key ("id ASC") to make the batch ordering # consistent. Therefore the primary key must be orderable, e.g. an integer # or a string. # # NOTE: By its nature, batch processing is subject to race conditions if # other processes are modifying the database. def in_batches: (?of: ::Integer of, ?start: untyped? start, ?finish: untyped? finish, ?load: bool load, ?error_on_ignore: untyped? error_on_ignore) { (untyped) -> untyped } -> (BatchEnumerator | untyped) def apply_limits: (untyped relation, untyped start, untyped finish) -> untyped def apply_start_limit: (untyped relation, untyped start) -> untyped def apply_finish_limit: (untyped relation, untyped finish) -> untyped def batch_order: () -> untyped def act_on_ignored_order: (untyped error_on_ignore) -> untyped end end module ActiveRecord module Calculations # 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}[rdoc-ref:QueryMethods#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}[rdoc-ref:QueryMethods#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}[rdoc-ref:QueryMethods#select], it will count the selected columns: # # Person.select(:age).count # # => counts the number of different age values # # Note: not all valid {Relation#select}[rdoc-ref:QueryMethods#select] expressions are valid #count expressions. The specifics differ # between databases. In invalid cases, an error from the database is thrown. def count: (?untyped? column_name) -> untyped # 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 def average: (untyped column_name) -> untyped # 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 def minimum: (untyped column_name) -> untyped # 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 def maximum: (untyped column_name) -> untyped # 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 def sum: (?untyped? column_name) -> untyped # 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 def calculate: (untyped operation, untyped column_name) -> untyped # Use #pluck as a shortcut to select one or more attributes without # loading a bunch of records just to grab the attributes you want. # # 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. # def pluck: (*untyped column_names) -> untyped # 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' ] def pick: (*untyped column_names) -> untyped # 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 def ids: () -> untyped def has_include?: (untyped column_name) -> untyped def perform_calculation: (untyped operation, untyped column_name) -> untyped def distinct_select?: (untyped column_name) -> untyped def aggregate_column: (untyped column_name) -> untyped def operation_over_aggregate_column: (untyped column, untyped operation, untyped distinct) -> untyped def execute_simple_calculation: (untyped operation, untyped column_name, untyped distinct) -> (0 | untyped) def execute_grouped_calculation: (untyped operation, untyped column_name, untyped distinct) -> untyped # Converts the given field to the value that the database adapter returns as # a usable column name: # # column_alias_for("users.id") # => "users_id" # column_alias_for("sum(id)") # => "sum_id" # column_alias_for("count(distinct users.id)") # => "count_distinct_users_id" # column_alias_for("count(*)") # => "count_all" def column_alias_for: (untyped field) -> untyped def type_for: (untyped field) { () -> untyped } -> untyped def type_cast_calculated_value: (untyped value, untyped `type`, ?untyped? operation) -> untyped def select_for_count: () -> untyped def build_count_subquery: (untyped relation, untyped column_name, untyped distinct) -> untyped end end module ActiveRecord module Delegation module DelegateCache # :nodoc: # :nodoc: def relation_delegate_class: (untyped klass) -> untyped def initialize_relation_delegate_cache: () -> untyped def inherited: (untyped child_class) -> untyped def generate_relation_method: (untyped method) -> untyped def include_relation_methods: (untyped delegate) -> untyped def generated_relation_methods: () -> untyped end class GeneratedRelationMethods < Module # :nodoc: include Mutex_m def generate_method: (untyped method) -> untyped end extend ActiveSupport::Concern module ClassSpecificRelation # :nodoc: extend ActiveSupport::Concern module ClassMethods # :nodoc: def name: () -> untyped end def method_missing: (untyped method, *untyped args) { () -> untyped } -> untyped end module ClassMethods # :nodoc: def create: (untyped klass, *untyped args, **untyped kwargs) -> untyped def relation_class_for: (untyped klass) -> untyped end def respond_to_missing?: (untyped method, untyped _) -> untyped end end module ActiveRecord module FinderMethods ONE_AS_ONE: ::String # 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. def find: (*untyped args) -> untyped # 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 def find_by: (untyped arg, *untyped args) -> untyped # Like #find_by, except that if no record is found, raises # an ActiveRecord::RecordNotFound error. def find_by!: (untyped arg, *untyped args) -> untyped # 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 def take: (?untyped? limit) -> untyped # Same as #take but raises ActiveRecord::RecordNotFound if no record # is found. Note that #take! accepts no arguments. def take!: () -> untyped # 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 # def first: (?untyped? limit) -> untyped # Same as #first but raises ActiveRecord::RecordNotFound if no record # is found. Note that #first! accepts no arguments. def first!: () -> untyped # 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: # # [#, #, #] # # and not: # # [#, #, #] def last: (?untyped? limit) -> untyped # Same as #last but raises ActiveRecord::RecordNotFound if no record # is found. Note that #last! accepts no arguments. def last!: () -> untyped # 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 def second: () -> untyped # Same as #second but raises ActiveRecord::RecordNotFound if no record # is found. def second!: () -> untyped # 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 def third: () -> untyped # Same as #third but raises ActiveRecord::RecordNotFound if no record # is found. def third!: () -> untyped # 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 def fourth: () -> untyped # Same as #fourth but raises ActiveRecord::RecordNotFound if no record # is found. def fourth!: () -> untyped # 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 def fifth: () -> untyped # Same as #fifth but raises ActiveRecord::RecordNotFound if no record # is found. def fifth!: () -> untyped # 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 def forty_two: () -> untyped # Same as #forty_two but raises ActiveRecord::RecordNotFound if no record # is found. def forty_two!: () -> untyped # 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 def third_to_last: () -> untyped # Same as #third_to_last but raises ActiveRecord::RecordNotFound if no record # is found. def third_to_last!: () -> untyped # 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 def second_to_last: () -> untyped # Same as #second_to_last but raises ActiveRecord::RecordNotFound if no record # is found. def second_to_last!: () -> untyped # 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 +find+-style conditions # (such as ['name LIKE ?', "%#{query}%"]). # * Hash - Finds the record that matches these +find+-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? def exists?: (?::Symbol conditions) -> (::FalseClass | untyped) def raise_record_not_found_exception!: (?untyped? ids, ?untyped? result_size, ?untyped? expected_size, ?untyped key, ?untyped? not_found_ids) -> untyped def offset_index: () -> untyped def construct_relation_for_exists: (untyped conditions) -> untyped def apply_join_dependency: (?eager_loading: untyped eager_loading) { (untyped, untyped) -> untyped } -> untyped def limited_ids_for: (untyped relation) -> untyped def using_limitable_reflections?: (untyped reflections) -> untyped def find_with_ids: (*untyped ids) -> (::Array[untyped] | untyped) def find_one: (untyped id) -> untyped def find_some: (untyped ids) -> untyped def find_some_ordered: (untyped ids) -> untyped def find_take: () -> untyped def find_take_with_limit: (untyped limit) -> untyped def find_nth: (untyped index) -> untyped def find_nth_with_limit: (untyped index, untyped limit) -> untyped def find_nth_from_last: (untyped index) -> untyped def find_last: (untyped limit) -> untyped def ordered_relation: () -> untyped end end module ActiveRecord class Relation extend ::ActiveRecord::Delegation::ClassMethods class FromClause # :nodoc: attr_reader value: untyped # :nodoc: attr_reader name: untyped def initialize: (untyped value, untyped name) -> untyped def merge: (untyped other) -> untyped def empty?: () -> untyped def ==: (untyped other) -> untyped def self.empty: () -> untyped end end end module ActiveRecord class Relation class HashMerger # :nodoc: attr_reader relation: untyped # :nodoc: attr_reader hash: untyped def initialize: (untyped relation, untyped hash) -> untyped def merge: () -> untyped # Applying values to a relation has some side effects. E.g. # interpolation might take place for where values. So we should # build a relation to merge in rather than directly merging # the values. def other: () -> untyped end class Merger # :nodoc: attr_reader relation: untyped # :nodoc: attr_reader values: untyped # :nodoc: attr_reader other: untyped def initialize: (untyped relation, untyped other) -> untyped NORMAL_VALUES: untyped def normal_values: () -> untyped def merge: () -> untyped def merge_preloads: () -> (nil | untyped) def merge_joins: () -> (nil | untyped) def merge_outer_joins: () -> (nil | untyped) def merge_multi_values: () -> untyped def merge_single_values: () -> untyped def merge_clauses: () -> untyped def replace_from_clause?: () -> untyped end end end module ActiveRecord class PredicateBuilder class ArrayHandler # :nodoc: def initialize: (untyped predicate_builder) -> untyped def call: (untyped attribute, untyped value) -> untyped attr_reader predicate_builder: untyped module NullPredicate # :nodoc: def self.or: (untyped other) -> untyped end end end end module ActiveRecord class PredicateBuilder class AssociationQueryValue # :nodoc: def initialize: (untyped associated_table, untyped value) -> untyped def queries: () -> ::Array[::Hash[untyped, untyped]] attr_reader associated_table: untyped attr_reader value: untyped def ids: () -> untyped def primary_key: () -> untyped def convert_to_id: (untyped value) -> untyped end end end module ActiveRecord class PredicateBuilder class BaseHandler # :nodoc: def initialize: (untyped predicate_builder) -> untyped def call: (untyped attribute, untyped value) -> untyped attr_reader predicate_builder: untyped end end end module ActiveRecord class PredicateBuilder class BasicObjectHandler # :nodoc: def initialize: (untyped predicate_builder) -> untyped def call: (untyped attribute, untyped value) -> untyped attr_reader predicate_builder: untyped end end end module ActiveRecord class PredicateBuilder class PolymorphicArrayValue # :nodoc: def initialize: (untyped associated_table, untyped values) -> untyped def queries: () -> untyped attr_reader associated_table: untyped attr_reader values: untyped def type_to_ids_mapping: () -> untyped def primary_key: (untyped value) -> untyped def klass: (untyped value) -> untyped def convert_to_id: (untyped value) -> untyped end end end module ActiveRecord class PredicateBuilder class RangeHandler # :nodoc: class RangeWithBinds < ::Struct[untyped] attr_accessor begin(): untyped attr_accessor end(): untyped attr_accessor exclude_end?(): untyped end def initialize: (untyped predicate_builder) -> untyped def call: (untyped attribute, untyped value) -> untyped attr_reader predicate_builder: untyped end end end module ActiveRecord class PredicateBuilder def initialize: (untyped table) -> untyped def build_from_hash: (untyped attributes) -> untyped def self.references: (untyped attributes) -> untyped # Define how a class is converted to Arel nodes when passed to +where+. # The handler can be any object that responds to +call+, and will be used # for any value that +===+ the class given. For example: # # MyCustomDateRange = Struct.new(:start, :end) # handler = proc do |column, range| # Arel::Nodes::Between.new(column, # Arel::Nodes::And.new([range.start, range.end]) # ) # end # ActiveRecord::PredicateBuilder.new("users").register_handler(MyCustomDateRange, handler) def register_handler: (untyped klass, untyped handler) -> untyped def build: (untyped attribute, untyped value) -> untyped def build_bind_attribute: (untyped column_name, untyped value) -> Arel::Nodes::BindParam def expand_from_hash: (untyped attributes) -> (::Array["1=0"] | untyped) attr_reader table: untyped def convert_dot_notation_to_hash: (untyped attributes) -> untyped def handler_for: (untyped object) -> untyped end end module ActiveRecord class PredicateBuilder class RelationHandler # :nodoc: def call: (untyped attribute, untyped value) -> untyped end end end module ActiveRecord class Relation class QueryAttribute < ActiveModel::Attribute # :nodoc: def type_cast: (untyped value) -> untyped def value_for_database: () -> untyped def with_cast_value: (untyped value) -> QueryAttribute def nil?: () -> untyped def infinite?: () -> untyped def unboundable?: () -> untyped def infinity?: (untyped value) -> untyped end end end module ActiveRecord module QueryMethods extend ActiveSupport::Concern include ActiveModel::ForbiddenAttributesProtection # WhereChain objects act as placeholder for queries in which #where does not have any parameter. # In this case, #where must be chained with #not to return a new relation. class WhereChain include ActiveModel::ForbiddenAttributesProtection def initialize: (untyped scope) -> untyped # 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') def not: (untyped opts, *untyped rest) -> untyped def not_behaves_as_nor?: (untyped opts) -> (::FalseClass | untyped) end FROZEN_EMPTY_ARRAY: untyped FROZEN_EMPTY_HASH: untyped # 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' }) def includes: (*untyped args) -> untyped def includes!: (*untyped args) -> untyped # 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" def eager_load: (*untyped args) -> untyped def eager_load!: (*untyped args) -> untyped # 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) def preload: (*untyped args) -> untyped def preload!: (*untyped args) -> untyped # 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) def extract_associated: (untyped association) -> untyped # 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 def references: (*untyped table_names) -> untyped def references!: (*untyped table_names) -> untyped # 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) # # => [#] # # 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) # # => [#] # # 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') # # => [#] # # 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 def select: (*untyped fields) -> untyped def _select!: (*untyped fields) -> untyped # 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. def reselect: (*untyped args) -> untyped def reselect!: (*untyped args) -> untyped # 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.group(:name) # # => [#, #] # # User.group('name AS grouped_name, age') # # => [#, #, #] # # Passing in an array of attributes to group by is also supported. # # User.select([:id, :first_name]).group(:id, :first_name).first(3) # # => [#, #, #] def group: (*untyped args) -> untyped def group!: (*untyped args) -> untyped # Allows to specify an order attribute: # # User.order(:name) # # SELECT "users".* FROM "users" ORDER BY "users"."name" ASC # # User.order(email: :desc) # # SELECT "users".* FROM "users" ORDER BY "users"."email" DESC # # User.order(:name, email: :desc) # # SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC # # 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 def order: (*untyped args) -> untyped def order!: (*untyped args) -> untyped # 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'. def reorder: (*untyped args) -> untyped def reorder!: (*untyped args) -> untyped VALID_UNSCOPING_VALUES: untyped # 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) } # def unscope: (*untyped args) -> untyped def unscope!: (*untyped args) -> untyped # Performs a 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" "comments_posts" # # ON "comments_posts"."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 def joins: (*untyped args) -> untyped def joins!: (*untyped args) -> untyped # Performs a left outer joins on +args+: # # User.left_outer_joins(:posts) # => SELECT "users".* FROM "users" LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id" # def left_outer_joins: (*untyped args) -> untyped def left_outer_joins!: (*untyped args) -> untyped # 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 #not to return a new relation that negates the where clause. # # User.where.not(name: "Jon") # # SELECT * FROM users WHERE name != 'Jon' # # See WhereChain for more details on #not. # # === blank condition # # If the condition is any blank-ish object, then #where is a no-op and returns # the current relation. def where: (?::Symbol opts, *untyped rest) -> untyped def where!: (untyped opts, *untyped rest) -> untyped # 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. def rewhere: (untyped conditions) -> untyped # 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). Neither relation may have a #limit, #offset, or #distinct set. # # Post.where("id = 1").or(Post.where("author_id = 3")) # # SELECT `posts`.* FROM `posts` WHERE ((id = 1) OR (author_id = 3)) # def or: (untyped other) -> untyped def or!: (untyped other) -> untyped # 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') def having: (untyped opts, *untyped rest) -> untyped def having!: (untyped opts, *untyped rest) -> untyped # 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' def limit: (untyped value) -> untyped def limit!: (untyped value) -> untyped # 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") def offset: (untyped value) -> untyped def offset!: (untyped value) -> untyped # Specifies locking settings (default to +true+). For more information # on locking, please see ActiveRecord::Locking. def lock: (?bool locks) -> untyped def lock!: (?bool locks) -> untyped # 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 # def none: () -> untyped def none!: () -> untyped # 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 def readonly: (?bool value) -> untyped def readonly!: (?bool value) -> untyped # 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' def create_with: (untyped value) -> untyped def create_with!: (untyped value) -> untyped # Specifies 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 # # Topic.select('a.title').from(Topic.approved, :a) # # SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a # def from: (untyped value, ?untyped? subquery_name) -> untyped def from!: (untyped value, ?untyped? subquery_name) -> untyped # 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 def distinct: (?bool value) -> untyped def distinct!: (?bool value) -> untyped # 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 def extending: (*untyped modules) { () -> untyped } -> untyped def extending!: (*untyped modules) { () -> untyped } -> untyped # 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" def optimizer_hints: (*untyped args) -> untyped def optimizer_hints!: (*untyped args) -> untyped # Reverse the existing order clause on the relation. # # User.order('name ASC').reverse_order # generated SQL has 'ORDER BY name DESC' def reverse_order: () -> untyped def reverse_order!: () -> untyped def skip_query_cache!: (?bool value) -> untyped def skip_preloading!: () -> untyped # 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. def annotate: (*untyped args) -> untyped def annotate!: (*untyped args) -> untyped def arel: (?untyped? aliases) -> untyped def construct_join_dependency: (untyped associations, untyped join_type) -> ActiveRecord::Associations::JoinDependency def build_subquery: (untyped subquery_alias, untyped select_value) -> untyped def assert_mutability!: () -> untyped def build_arel: (untyped aliases) -> untyped def build_from: () -> untyped def select_association_list: (untyped associations) { () -> untyped } -> untyped def valid_association_list: (untyped associations) -> untyped def build_left_outer_joins: (untyped manager, untyped outer_joins, untyped aliases) -> untyped def build_joins: (untyped manager, untyped joins, untyped aliases) -> untyped def build_join_query: (untyped manager, untyped buckets, untyped join_type, untyped aliases) -> untyped def build_select: (untyped arel) -> untyped def arel_columns: (untyped columns) -> untyped def arel_column: (untyped field) { (untyped) -> untyped } -> untyped def table_name_matches?: (untyped from) -> untyped def reverse_sql_order: (untyped order_query) -> (::Array[untyped] | untyped) def does_not_support_reverse?: (untyped order) -> untyped def build_order: (untyped arel) -> untyped VALID_DIRECTIONS: untyped def validate_order_args: (untyped args) -> untyped def preprocess_order_args: (untyped order_args) -> untyped def order_column: (untyped field) -> untyped # Checks to make sure that the arguments are not blank. Note that if some # blank-like object were initially passed into the query method, then this # method will not raise an error. # # Example: # # Post.references() # raises an error # Post.references([]) # does not raise an error # # This particular method should be called with a method_name and the args # passed into that method as an input. For example: # # def references(*args) # check_if_method_has_arguments!("references", args) # ... # end def check_if_method_has_arguments!: (untyped method_name, untyped args) -> untyped STRUCTURAL_OR_METHODS: untyped def structurally_incompatible_values_for_or: (untyped other) -> untyped def where_clause_factory: () -> untyped DEFAULT_VALUES: ::Hash[untyped, untyped] end end module ActiveRecord # = Active Record \Relation class Relation MULTI_VALUE_METHODS: ::Array[untyped] SINGLE_VALUE_METHODS: ::Array[untyped] CLAUSE_METHODS: ::Array[untyped] INVALID_METHODS_FOR_DELETE_ALL: ::Array[untyped] VALUE_METHODS: untyped include Enumerable[untyped, untyped] include FinderMethods include Calculations include SpawnMethods include QueryMethods include Batches include Explain include Delegation attr_reader table: untyped attr_reader klass: untyped attr_reader loaded: untyped attr_reader predicate_builder: untyped attr_accessor skip_preloading_value: untyped def initialize: (untyped klass, ?values: ::Hash[untyped, untyped] values, ?predicate_builder: untyped predicate_builder, ?table: untyped table) -> untyped def initialize_copy: (untyped other) -> untyped def arel_attribute: (untyped name) -> untyped def bind_attribute: (untyped name, untyped value) { (untyped, untyped) -> untyped } -> untyped # Initializes new record from relation while maintaining the current # scope. # # Expects arguments in the same format as {ActiveRecord::Base.new}[rdoc-ref:Core.new]. # # users = User.where(name: 'DHH') # user = users.new # => # # # You can also pass a block to new with the new record as argument: # # user = users.new { |user| user.name = 'Oscar' } # user.name # => Oscar def new: (?untyped? attributes) { () -> untyped } -> untyped # 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}[rdoc-ref:Persistence::ClassMethods#create]. # # ==== Examples # # users = User.where(name: 'Oscar') # users.create # => # # # users.create(name: 'fxn') # users.create # => # # # users.create { |user| user.name = 'tenderlove' } # # => # # # users.create(name: nil) # validation on name # # => # def create: (?untyped? attributes) { () -> untyped } -> untyped # Similar to #create, but calls # {create!}[rdoc-ref:Persistence::ClassMethods#create!] # on the base class. Raises an exception if a validation error occurs. # # Expects arguments in the same format as # {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]. def create!: (?untyped? attributes) { () -> untyped } -> untyped def first_or_create: (?untyped? attributes) { () -> untyped } -> untyped def first_or_create!: (?untyped? attributes) { () -> untyped } -> untyped def first_or_initialize: (?untyped? attributes) { () -> untyped } -> untyped # 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(trim non-ascii characters)lope" or create a new one. # User.find_or_create_by(first_name: 'Pen(trim non-ascii characters)lope') # # => # # # # Find the first user named "Pen(trim non-ascii characters)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(trim non-ascii characters)lope') # # => # # # # 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') # # => # # # 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 # # different last name. # User.find_or_create_by(first_name: 'Scarlett') do |user| # user.last_name = 'Johansson' # end # # => # # # 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. def find_or_create_by: (untyped attributes) { () -> untyped } -> untyped # Like #find_or_create_by, but calls # {create!}[rdoc-ref:Persistence::ClassMethods#create!] so an exception # is raised if the created record is invalid. def find_or_create_by!: (untyped attributes) { () -> untyped } -> untyped # Attempts to create a record with the given attributes in a table that has a unique 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 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. def create_or_find_by: (untyped attributes) { () -> untyped } -> untyped # Like #create_or_find_by, but calls # {create!}[rdoc-ref:Persistence::ClassMethods#create!] so an exception # is raised if the created record is invalid. def create_or_find_by!: (untyped attributes) { () -> untyped } -> untyped # Like #find_or_create_by, but calls {new}[rdoc-ref:Core#new] # instead of {create}[rdoc-ref:Persistence::ClassMethods#create]. def find_or_initialize_by: (untyped attributes) { () -> untyped } -> untyped # 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}[https://guides.rubyonrails.org/active_record_querying.html#running-explain]. def explain: () -> untyped # Converts relation objects to Array. def to_ary: () -> untyped def records: () -> untyped # Serializes the relation objects Array. def encode_with: (untyped coder) -> untyped # Returns size of the records. def size: () -> untyped # Returns true if there are no records. def empty?: () -> untyped # Returns true if there are no records. def none?: () -> untyped # Returns true if there are any records. def any?: () -> untyped # Returns true if there is exactly one record. def one?: () -> untyped # Returns true if there is more than one record. def many?: () -> untyped # 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) def cache_key: (?::Symbol timestamp_column) -> untyped def compute_cache_key: (?::Symbol timestamp_column) -> untyped # 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%') def cache_version: (?::Symbol timestamp_column) -> untyped def compute_cache_version: (untyped timestamp_column) -> untyped # Returns a cache key along with the version. def cache_key_with_version: () -> untyped # 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 # # Please check unscoped if you want to remove all previous scopes (including # the default_scope) during the execution of a block. def scoping: () { () -> untyped } -> untyped def _exec_scope: (untyped name, *untyped args) { () -> untyped } -> untyped # 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. # # 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') def update_all: (untyped updates) -> untyped def update: (?::Symbol id, untyped attributes) -> untyped def update_counters: (untyped counters) -> untyped # Touches all records in the current relation without instantiating records first with the +updated_at+/+updated_on+ attributes # set to the current time or the time specified. # 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'" def touch_all: (*untyped names, ?time: untyped? time) -> untyped # Destroys the records by instantiating each # record and calling its {#destroy}[rdoc-ref:Persistence#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 def destroy_all: () -> untyped # Deletes the records without instantiating the records # first, and hence not calling the {#destroy}[rdoc-ref:Persistence#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 def delete_all: () -> untyped # 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) def destroy_by: (*untyped args) -> untyped # 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) def delete_by: (*untyped args) -> untyped # 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 # => # def load: () { () -> untyped } -> untyped # Forces reloading of relation. def reload: () -> untyped def reset: () -> untyped # Returns sql statement for the relation. # # User.where(name: 'Oscar').to_sql # # => SELECT "users".* FROM "users" WHERE "users"."name" = 'Oscar' def to_sql: () -> untyped # Returns a hash of where conditions. # # User.where(name: 'Oscar').where_values_hash # # => {name: "Oscar"} def where_values_hash: (?untyped relation_table_name) -> untyped def scope_for_create: () -> untyped # Returns true if relation needs eager loading. def eager_loading?: () -> untyped # 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] } def joined_includes_values: () -> untyped # Compares two relations for equality. def ==: (untyped other) -> untyped def pretty_print: (untyped q) -> untyped # Returns true if relation is blank. def blank?: () -> untyped def values: () -> untyped def inspect: () -> ::String def empty_scope?: () -> untyped def has_limit_or_offset?: () -> untyped def alias_tracker: (?untyped joins, ?untyped? aliases) -> untyped def preload_associations: (untyped records) -> untyped attr_reader _deprecated_scope_source: untyped attr_writer _deprecated_scope_source: untyped def load_records: (untyped records) -> untyped def null_relation?: () -> untyped def already_in_scope?: () -> untyped def _deprecated_spawn: (untyped name) -> untyped def _deprecated_scope_block: (untyped name) { (untyped) -> untyped } -> untyped def _scoping: (untyped scope) { () -> untyped } -> untyped def _substitute_values: (untyped values) -> untyped def _increment_attribute: (untyped attribute, ?::Integer value) -> untyped def exec_queries: () { () -> untyped } -> untyped def skip_query_cache_if_necessary: () { () -> untyped } -> untyped def build_preloader: () -> ActiveRecord::Associations::Preloader def references_eager_loaded_tables?: () -> untyped def tables_in_string: (untyped string) -> (::Array[untyped] | untyped) end end module ActiveRecord class Relation module RecordFetchWarning # 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. def exec_queries: () -> untyped class QueryRegistry # :nodoc: extend ActiveSupport::PerThreadRegistry attr_reader queries: untyped def initialize: () -> untyped def reset: () -> untyped end end end end module ActiveRecord module SpawnMethods def spawn: () -> untyped # 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. def merge: (untyped other) -> untyped def merge!: (untyped other) -> untyped # 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 def except: (*untyped skips) -> untyped # 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 def only: (*untyped onlies) -> untyped def relation_with: (untyped values) -> untyped end end module ActiveRecord class Relation class WhereClauseFactory # :nodoc: def initialize: (untyped klass, untyped predicate_builder) -> untyped def build: (untyped opts, untyped other) -> WhereClause attr_reader klass: untyped attr_reader predicate_builder: untyped end end end module ActiveRecord class Relation class WhereClause def initialize: (untyped predicates) -> untyped def +: (untyped other) -> WhereClause def -: (untyped other) -> WhereClause def merge: (untyped other) -> WhereClause def except: (*untyped columns) -> WhereClause def or: (untyped other) -> untyped def to_h: (?untyped? table_name) -> untyped def ast: () -> Arel::Nodes::And def ==: (untyped other) -> untyped def invert: (?::Symbol as) -> WhereClause def self.empty: () -> untyped attr_reader predicates: untyped def referenced_columns: () -> untyped def equalities: (untyped predicates) -> untyped def predicates_unreferenced_by: (untyped other) -> untyped def equality_node?: (untyped node) -> untyped def invert_predicate: (untyped node) -> untyped def except_predicates: (untyped columns) -> untyped def predicates_with_wrapped_sql_literals: () -> untyped ARRAY_WITH_EMPTY_STRING: ::Array[untyped] def non_empty_predicates: () -> untyped def wrap_sql_literal: (untyped node) -> Arel::Nodes::Grouping def extract_node_value: (untyped node) -> untyped end end end module ActiveRecord # # # This class encapsulates a result returned from calling # {#exec_query}[rdoc-ref:ConnectionAdapters::DatabaseStatements#exec_query] # on any database connection adapter. For example: # # result = ActiveRecord::Base.connection.exec_query('SELECT id, title, body FROM posts') # result # => # # # # 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 class Result include Enumerable[untyped, untyped] attr_reader columns: untyped attr_reader rows: untyped attr_reader column_types: untyped def initialize: (untyped columns, untyped rows, ?::Hash[untyped, untyped] column_types) -> untyped # Returns true if this result set includes the column named +name+ def includes_column?: (untyped name) -> untyped # Returns the number of elements in the rows array. def length: () -> untyped # Calls the given block once for each element in row collection, passing # row as parameter. # # Returns an +Enumerator+ if no block is given. def each: () { (untyped) -> untyped } -> untyped def to_hash: () -> untyped # Returns true if there are no records, otherwise false. def empty?: () -> untyped # Returns an array of hashes representing each row record. def to_ary: () -> untyped def []: (untyped idx) -> untyped # Returns the first record from the rows collection. # If the rows collection is empty, returns +nil+. def first: () -> (nil | untyped) # Returns the last record from the rows collection. # If the rows collection is empty, returns +nil+. def last: () -> (nil | untyped) def cast_values: (?::Hash[untyped, untyped] type_overrides) -> untyped def initialize_copy: (untyped other) -> untyped def column_type: (untyped name, ?::Hash[untyped, untyped] type_overrides) -> untyped def hash_rows: () -> untyped end end module ActiveRecord class RuntimeRegistry # This is a thread locals registry for Active Record. For example: # # ActiveRecord::RuntimeRegistry.connection_handler # # returns the connection handler local to the current thread. # # See the documentation of ActiveSupport::PerThreadRegistry # for further details. # :nodoc: extend ActiveSupport::PerThreadRegistry attr_accessor connection_handler: untyped attr_accessor sql_runtime: untyped end end module ActiveRecord module Sanitization extend ActiveSupport::Concern module ClassMethods # 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'" def sanitize_sql_for_conditions: (untyped condition) -> (nil | untyped) # 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'" def sanitize_sql_for_assignment: (untyped assignments, ?untyped default_table_name) -> untyped # Accepts an array, or string of SQL conditions and sanitizes # them into a valid SQL fragment for an ORDER clause. # # sanitize_sql_for_order(["field(id, ?)", [1,3,2]]) # # => "field(id, 1,3,2)" # # sanitize_sql_for_order("id ASC") # # => "id ASC" def sanitize_sql_for_order: (untyped condition) -> untyped # 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" def sanitize_sql_hash_for_assignment: (untyped attrs, untyped table) -> untyped # 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 "\", "_" and "%". # # sanitize_sql_like("100%") # # => "100\\%" # # sanitize_sql_like("snake_cased_string") # # => "snake\\_cased\\_string" # # sanitize_sql_like("100%", "!") # # => "100!%" # # sanitize_sql_like("snake_cased_string", "!") # # => "snake!_cased!_string" def sanitize_sql_like: (untyped string, ?::String escape_character) -> untyped # 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'" def sanitize_sql_array: (untyped ary) -> untyped def disallow_raw_sql!: (untyped args, ?permit: untyped permit) -> (nil | untyped) def replace_bind_variables: (untyped statement, untyped values) -> untyped def replace_bind_variable: (untyped value, ?untyped c) -> untyped def replace_named_bind_variables: (untyped statement, untyped bind_vars) -> untyped def quote_bound_value: (untyped value, ?untyped c) -> untyped def raise_if_bind_arity_mismatch: (untyped statement, untyped expected, untyped provided) -> untyped end end end module ActiveRecord class SchemaDumper def self.dump: (?untyped connection, ?untyped stream, ?untyped config) -> untyped def self.generate_options: (untyped config) -> { table_name_prefix: untyped, table_name_suffix: untyped } def dump: (untyped stream) -> untyped attr_accessor table_name: untyped def initialize: (untyped connection, ?::Hash[untyped, untyped] options) -> untyped # turns 20170404131909 into "2017_04_04_131909" def formatted_version: () -> untyped def define_params: () -> untyped def header: (untyped stream) -> untyped def trailer: (untyped stream) -> untyped # extensions are only supported by PostgreSQL def extensions: (untyped stream) -> nil def tables: (untyped stream) -> untyped def table: (untyped table, untyped stream) -> untyped # Keep it for indexing materialized views def indexes: (untyped table, untyped stream) -> untyped def indexes_in_create: (untyped table, untyped stream) -> untyped def index_parts: (untyped index) -> untyped def foreign_keys: (untyped table, untyped stream) -> untyped def format_colspec: (untyped colspec) -> untyped def format_options: (untyped options) -> untyped def format_index_parts: (untyped options) -> untyped def remove_prefix_and_suffix: (untyped table) -> untyped def ignored?: (untyped table_name) -> untyped end end module ActiveRecord class SchemaMigration < ActiveRecord::Base def self._internal?: () -> ::TrueClass def self.primary_key: () -> "version" def self.table_name: () -> ::String def self.table_exists?: () -> untyped def self.create_table: () -> untyped def self.drop_table: () -> untyped def self.normalize_migration_number: (untyped number) -> untyped def self.normalized_versions: () -> untyped def self.all_versions: () -> untyped def version: () -> untyped end end module ActiveRecord # = 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.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. class Schema < Migration::Current # 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}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table], # {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#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.define(version: 2038_01_19_000001) do # ... # end def self.define: (?::Hash[untyped, untyped] info) { () -> untyped } -> untyped def define: (untyped info) { () -> untyped } -> untyped end end module ActiveRecord module Scoping module Default extend ActiveSupport::Concern module ClassMethods # 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" # } def unscoped: () { () -> untyped } -> untyped def scope_attributes?: () -> untyped def before_remove_const: () -> untyped def default_scope: (?untyped? scope) { () -> untyped } -> untyped def build_default_scope: (?untyped relation) -> (nil | untyped) def ignore_default_scope?: () -> untyped def ignore_default_scope=: (untyped ignore) -> untyped # The ignore_default_scope flag is used to prevent an infinite recursion # situation where a default scope references a scope which has a default # scope which references a scope... def evaluate_default_scope: () { () -> untyped } -> (nil | untyped) end end end end module ActiveRecord # = Active Record \Named \Scopes module Scoping module Named extend ActiveSupport::Concern module ClassMethods # 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}[rdoc-ref:Scoping::Default::ClassMethods#default_scope]. def all: () -> untyped def scope_for_association: (?untyped scope) -> untyped # Returns a scope for the model with default scopes. def default_scoped: (?untyped scope) -> untyped def default_extensions: () -> untyped # 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}[rdoc-ref:Scoping::Named::ClassMethods#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'). # # You should always pass a callable object to the scopes defined # with #scope. This ensures that the scope is re-evaluated each # time it is called. # # 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}[rdoc-ref:Associations::ClassMethods#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}[rdoc-ref:Associations::ClassMethods#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}[rdoc-ref:Associations::ClassMethods#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 def scope: (untyped name, untyped body) { () -> untyped } -> untyped def valid_scope_name?: (untyped name) -> untyped end end end end module ActiveRecord module Scoping extend ActiveSupport::Concern include Default include Named module ClassMethods # :nodoc: # Collects attributes from scopes that should be applied when creating # an AR instance for the particular class this is called on. def scope_attributes: () -> untyped # Are there attributes associated with this scope? def scope_attributes?: () -> untyped def current_scope: (?bool skip_inherited_scope) -> untyped def current_scope=: (untyped scope) -> untyped end def populate_with_current_scope_attributes: () -> (nil | untyped) def initialize_internals_callback: () -> untyped class ScopeRegistry # This class stores the +:current_scope+ and +:ignore_default_scope+ values # for different classes. The registry is stored as a thread local, which is # accessed through +ScopeRegistry.current+. # # This class allows you to store and get the scope values on different # classes and different types of scopes. For example, if you are attempting # to get the current_scope for the +Board+ model, then you would use the # following code: # # registry = ActiveRecord::Scoping::ScopeRegistry # registry.set_value_for(:current_scope, Board, some_new_scope) # # Now when you run: # # registry.value_for(:current_scope, Board) # # You will obtain whatever was defined in +some_new_scope+. The #value_for # and #set_value_for methods are delegated to the current ScopeRegistry # object, so the above example code can also be called as: # # ActiveRecord::Scoping::ScopeRegistry.set_value_for(:current_scope, # Board, some_new_scope) # :nodoc: extend ActiveSupport::PerThreadRegistry VALID_SCOPE_TYPES: ::Array[untyped] def initialize: () -> untyped # Obtains the value for a given +scope_type+ and +model+. def value_for: (untyped scope_type, untyped model, ?bool skip_inherited_scope) -> untyped # Sets the +value+ for a given +scope_type+ and +model+. def set_value_for: (untyped scope_type, untyped model, untyped value) -> untyped def raise_invalid_scope_type!: (untyped scope_type) -> untyped end end end module ActiveRecord module SecureToken extend ActiveSupport::Concern module ClassMethods # Example using #has_secure_token # # # Schema: User(token:string, auth_token:string) # class User < ActiveRecord::Base # has_secure_token # has_secure_token :auth_token # end # # user = User.new # user.save # user.token # => "pX27zsMN2ViQKta1bGfLmVJE" # user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7" # user.regenerate_token # => true # user.regenerate_auth_token # => true # # SecureRandom::base58 is used to generate the 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}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can. # You're encouraged to add a unique index in the database to deal with this even more unlikely scenario. def has_secure_token: (?::Symbol attribute) -> untyped def generate_unique_secure_token: () -> untyped end end end module ActiveRecord # nodoc: # = Active Record \Serialization module Serialization extend ActiveSupport::Concern include ActiveModel::Serializers::JSON def serializable_hash: (?untyped? options) -> untyped end end module ActiveRecord class StatementCache class Substitute end class Query # :nodoc: def initialize: (untyped sql) -> untyped def sql_for: (untyped binds, untyped connection) -> untyped end class PartialQuery < Query # :nodoc: def initialize: (untyped values) -> untyped def sql_for: (untyped binds, untyped connection) -> untyped end class PartialQueryCollector def initialize: () -> untyped def <<: (untyped str) -> untyped def add_bind: (untyped obj) -> untyped def value: () -> ::Array[untyped] end def self.query: (untyped sql) -> Query def self.partial_query: (untyped values) -> PartialQuery def self.partial_query_collector: () -> PartialQueryCollector class Params # :nodoc: def bind: () -> Substitute end class BindMap # :nodoc: def initialize: (untyped bound_attributes) -> untyped def bind: (untyped values) -> untyped end def self.create: (untyped connection, ?untyped? callable) { () -> untyped } -> untyped def initialize: (untyped query_builder, untyped bind_map, untyped klass) -> untyped def execute: (untyped params, untyped connection) { () -> untyped } -> untyped def self.unsupported_value?: (untyped value) -> untyped attr_reader query_builder: untyped attr_reader bind_map: untyped attr_reader klass: untyped end end module ActiveRecord # 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 (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+ # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store]. # Simply use {.store_accessor}[rdoc-ref:ClassMethods#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', 'red'] # # # 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}[rdoc-ref:rdoc-ref:ClassMethods#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 module Store extend ActiveSupport::Concern attr_accessor local_stored_attributes: untyped module ClassMethods def store: (untyped store_attribute, ?::Hash[untyped, untyped] options) -> untyped def store_accessor: (untyped store_attribute, *untyped keys, ?suffix: untyped? suffix, ?prefix: untyped? prefix) -> (::FalseClass | nil | untyped) def _store_accessors_module: () -> untyped def stored_attributes: () -> untyped end def read_store_attribute: (untyped store_attribute, untyped key) -> untyped def write_store_attribute: (untyped store_attribute, untyped key, untyped value) -> untyped def store_accessor_for: (untyped store_attribute) -> untyped class HashAccessor # :nodoc: def self.read: (untyped object, untyped attribute, untyped key) -> untyped def self.write: (untyped object, untyped attribute, untyped key, untyped value) -> untyped def self.prepare: (untyped object, untyped attribute) -> untyped end class StringKeyedHashAccessor < HashAccessor # :nodoc: def self.read: (untyped object, untyped attribute, untyped key) -> untyped def self.write: (untyped object, untyped attribute, untyped key, untyped value) -> untyped end class IndifferentHashAccessor < ActiveRecord::Store::HashAccessor # :nodoc: def self.prepare: (untyped object, untyped store_attribute) -> untyped end class IndifferentCoder # :nodoc: def initialize: (untyped attr_name, untyped coder_or_class_name) -> untyped def dump: (untyped obj) -> untyped def load: (untyped yaml) -> untyped def self.as_indifferent_hash: (untyped obj) -> untyped end end end module ActiveRecord # 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 module Suppressor extend ActiveSupport::Concern module ClassMethods def suppress: () { () -> untyped } -> untyped end def save: () -> untyped def save!: () -> untyped end class SuppressorRegistry # :nodoc: extend ActiveSupport::PerThreadRegistry attr_reader suppressed: untyped def initialize: () -> untyped end end module ActiveRecord class TableMetadata def initialize: (untyped klass, untyped arel_table, ?untyped? association, ?untyped types) -> untyped def resolve_column_aliases: (untyped hash) -> untyped def arel_attribute: (untyped column_name) -> untyped def `type`: (untyped column_name) -> untyped def has_column?: (untyped column_name) -> untyped def associated_with?: (untyped association_name) -> untyped def associated_table: (untyped table_name) -> untyped def associated_predicate_builder: (untyped table_name) -> untyped def polymorphic_association?: () -> untyped def aggregated_with?: (untyped aggregation_name) -> untyped def reflect_on_aggregation: (untyped aggregation_name) -> untyped def predicate_builder: () -> untyped attr_reader klass: untyped attr_reader types: untyped attr_reader arel_table: untyped attr_reader association: untyped end end module ActiveRecord module Tasks class DatabaseAlreadyExists < StandardError end class DatabaseNotSupported < StandardError end # 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') module DatabaseTasks attr_writer current_config: untyped attr_writer db_dir: untyped attr_writer migrations_paths: untyped attr_writer fixtures_path: untyped attr_writer root: untyped attr_writer env: untyped attr_writer seed_loader: untyped attr_accessor database_configuration: untyped LOCAL_HOSTS: ::Array[untyped] def check_protected_environments!: () -> untyped def register_task: (untyped pattern, untyped task) -> untyped def db_dir: () -> untyped def migrations_paths: () -> untyped def fixtures_path: () -> untyped def root: () -> untyped def env: () -> untyped def spec: () -> untyped def seed_loader: () -> untyped def current_config: (?::Hash[untyped, untyped] options) -> untyped def create: (*untyped arguments) -> untyped def create_all: () -> untyped def setup_initial_database_yaml: () -> (::Hash[untyped, untyped] | untyped) def for_each: (untyped databases) { (untyped) -> untyped } -> (::Hash[untyped, untyped] | nil | untyped) def raise_for_multi_db: (?untyped environment, command: untyped command) -> untyped def create_current: (?untyped environment, ?untyped? spec_name) -> untyped def drop: (*untyped arguments) -> untyped def drop_all: () -> untyped def drop_current: (?untyped environment) -> untyped def truncate_tables: (untyped configuration) -> untyped def truncate_all: (?untyped environment) -> untyped def migrate: () -> untyped def migrate_status: () -> untyped def check_target_version: () -> untyped def target_version: () -> untyped def charset_current: (?untyped environment, ?untyped specification_name) -> untyped def charset: (*untyped arguments) -> untyped def collation_current: (?untyped environment, ?untyped specification_name) -> untyped def collation: (*untyped arguments) -> untyped def purge: (untyped configuration) -> untyped def purge_all: () -> untyped def purge_current: (?untyped environment) -> untyped def structure_dump: (*untyped arguments) -> untyped def structure_load: (*untyped arguments) -> untyped def load_schema: (untyped configuration, ?untyped format, ?untyped? file, ?untyped environment, ?::String spec_name) -> untyped def schema_up_to_date?: (untyped configuration, ?untyped format, ?untyped? file, ?untyped environment, ?::String spec_name) -> (::TrueClass | ::FalseClass | untyped) def reconstruct_from_schema: (untyped configuration, ?untyped format, ?untyped? file, ?untyped environment, ?::String spec_name) -> untyped def dump_schema: (untyped configuration, ?untyped format, ?::String spec_name) -> untyped def schema_file: (?untyped format) -> untyped def schema_file_type: (?untyped format) -> untyped def dump_filename: (untyped namespace, ?untyped format) -> untyped def cache_dump_filename: (untyped namespace) -> untyped def load_schema_current: (?untyped format, ?untyped? file, ?untyped environment) -> untyped def check_schema_file: (untyped filename) -> untyped def load_seed: () -> untyped # 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") def dump_schema_cache: (untyped conn, untyped filename) -> untyped def verbose?: () -> untyped def class_for_adapter: (untyped adapter) -> untyped def each_current_configuration: (untyped environment, ?untyped? spec_name) { (untyped, untyped, untyped) -> untyped } -> untyped def each_local_configuration: () { (untyped) -> untyped } -> untyped def local_database?: (untyped configuration) -> untyped def schema_sha1: (untyped file) -> untyped end end end module ActiveRecord module Tasks class MySQLDatabaseTasks # :nodoc: # :nodoc: ER_DB_CREATE_EXISTS: ::Integer def initialize: (untyped configuration) -> untyped def create: () -> untyped def drop: () -> untyped def purge: () -> untyped def charset: () -> untyped def collation: () -> untyped def structure_dump: (untyped filename, untyped extra_flags) -> untyped def structure_load: (untyped filename, untyped extra_flags) -> untyped attr_reader configuration: untyped def configuration_without_database: () -> untyped def creation_options: () -> untyped def prepare_command_options: () -> untyped def run_cmd: (untyped cmd, untyped args, untyped action) -> untyped def run_cmd_error: (untyped cmd, untyped args, untyped action) -> untyped end end end module ActiveRecord module Tasks class PostgreSQLDatabaseTasks # :nodoc: # :nodoc: DEFAULT_ENCODING: untyped ON_ERROR_STOP_1: ::String SQL_COMMENT_BEGIN: ::String def initialize: (untyped configuration) -> untyped def create: (?bool master_established) -> untyped def drop: () -> untyped def charset: () -> untyped def collation: () -> untyped def purge: () -> untyped def structure_dump: (untyped filename, untyped extra_flags) -> untyped def structure_load: (untyped filename, untyped extra_flags) -> untyped attr_reader configuration: untyped def encoding: () -> untyped def establish_master_connection: () -> untyped def set_psql_env: () -> untyped def run_cmd: (untyped cmd, untyped args, untyped action) -> untyped def run_cmd_error: (untyped cmd, untyped args, untyped action) -> untyped def remove_sql_header_comments: (untyped filename) -> untyped end end end module ActiveRecord module Tasks class SQLiteDatabaseTasks def initialize: (untyped configuration, ?untyped root) -> untyped def create: () -> untyped def drop: () -> untyped def purge: () -> untyped def charset: () -> untyped def structure_dump: (untyped filename, untyped extra_flags) -> untyped def structure_load: (untyped filename, untyped extra_flags) -> untyped attr_reader configuration: untyped attr_reader root: untyped def run_cmd: (untyped cmd, untyped args, untyped `out`) -> untyped def run_cmd_error: (untyped cmd, untyped args) -> untyped end end end module ActiveRecord module TestDatabases def self.create_and_load_schema: (untyped i, env_name: untyped env_name) -> untyped end end module ActiveRecord module TestFixtures extend ActiveSupport::Concern def before_setup: () -> untyped def after_teardown: () -> untyped module ClassMethods # 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. def set_fixture_class: (?::Hash[untyped, untyped] class_names) -> untyped def fixtures: (*untyped fixture_set_names) -> untyped def setup_fixture_accessors: (?untyped? fixture_set_names) -> untyped def uses_transaction: (*untyped methods) -> untyped def uses_transaction?: (untyped method) -> untyped end def run_in_transaction?: () -> untyped def setup_fixtures: (?untyped config) -> untyped def teardown_fixtures: () -> untyped def enlist_fixture_connections: () -> untyped # Shares the writing connection pool with connections on # other handlers. # # In an application with a primary and replica the test fixtures # need to share a connection pool so that the reading connection # can see data in the open transaction on the writing connection. def setup_shared_connection_pool: () -> (nil | untyped) def load_fixtures: (untyped config) -> untyped def instantiate_fixtures: () -> untyped def load_instances?: () -> untyped end end module ActiveRecord # = 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 module Timestamp extend ActiveSupport::Concern def initialize_dup: (untyped other) -> untyped module ClassMethods # :nodoc: def touch_attributes_with_time: (*untyped names, ?time: untyped? time) -> untyped def timestamp_attributes_for_create_in_model: () -> untyped def timestamp_attributes_for_update_in_model: () -> untyped def all_timestamp_attributes_in_model: () -> untyped def current_time_from_proper_timezone: () -> untyped def timestamp_attributes_for_create: () -> ::Array["created_at" | "created_on"] def timestamp_attributes_for_update: () -> ::Array["updated_at" | "updated_on"] def reload_schema_from_cache: () -> untyped end def _create_record: () -> untyped def _update_record: () -> untyped def create_or_update: (?touch: bool touch) -> untyped def should_record_timestamps?: () -> untyped def timestamp_attributes_for_create_in_model: () -> untyped def timestamp_attributes_for_update_in_model: () -> untyped def all_timestamp_attributes_in_model: () -> untyped def current_time_from_proper_timezone: () -> untyped def max_updated_column_timestamp: () -> untyped # Clear attributes and changed_attributes def clear_timestamp_attributes: () -> untyped end end module ActiveRecord module TouchLater # = Active Record Touch Later # :nodoc: extend ActiveSupport::Concern def touch_later: (*untyped names) -> untyped def touch: (*untyped names, ?time: untyped? time) -> untyped def surreptitiously_touch: (untyped attrs) -> untyped def touch_deferred_attributes: () -> untyped def has_defer_touch_attrs?: () -> untyped def belongs_to_touch_method: () -> :touch_later end end module ActiveRecord # See ActiveRecord::Transactions::ClassMethods for documentation. module Transactions extend ActiveSupport::Concern # nodoc: ACTIONS: ::Array[untyped] # = 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}[rdoc-ref:Persistence#save] and # {#destroy}[rdoc-ref:Persistence#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. This works on MySQL and PostgreSQL. SQLite3 version >= '3.6.8' also supports it. # # 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 on MySQL and PostgreSQL. See # https://dev.mysql.com/doc/refman/5.7/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! module ClassMethods # See the ConnectionAdapters::DatabaseStatements#transaction API docs. def transaction: (**untyped options) { () -> untyped } -> untyped def before_commit: (*untyped args) { () -> untyped } -> untyped # 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] # def after_commit: (*untyped args) { () -> untyped } -> untyped # Shortcut for after_commit :hook, on: [ :create, :update ]. def after_save_commit: (*untyped args) { () -> untyped } -> untyped # Shortcut for after_commit :hook, on: :create. def after_create_commit: (*untyped args) { () -> untyped } -> untyped # Shortcut for after_commit :hook, on: :update. def after_update_commit: (*untyped args) { () -> untyped } -> untyped # Shortcut for after_commit :hook, on: :destroy. def after_destroy_commit: (*untyped args) { () -> untyped } -> untyped # This callback is called after a create, update, or destroy are rolled back. # # Please check the documentation of #after_commit for options. def after_rollback: (*untyped args) { () -> untyped } -> untyped def before_commit_without_transaction_enrollment: (*untyped args) { () -> untyped } -> untyped def after_commit_without_transaction_enrollment: (*untyped args) { () -> untyped } -> untyped def after_rollback_without_transaction_enrollment: (*untyped args) { () -> untyped } -> untyped def set_options_for_callbacks!: (untyped args, ?::Hash[untyped, untyped] enforced_options) -> untyped def assert_valid_transaction_action: (untyped actions) -> untyped end # See ActiveRecord::Transactions::ClassMethods for detailed documentation. def transaction: (?::Hash[untyped, untyped] options) { () -> untyped } -> untyped def destroy: () -> untyped def save: () -> untyped def save!: () -> untyped def touch: () -> untyped def before_committed!: () -> untyped def committed!: (?should_run_callbacks: bool should_run_callbacks) -> untyped def rolledback!: (?should_run_callbacks: bool should_run_callbacks, ?force_restore_state: bool force_restore_state) -> untyped # Executes +method+ within a transaction and captures its return value as a # status flag. If the status is true the transaction is committed, otherwise # a ROLLBACK is issued. In any case the status flag is returned. # # This method is available within the context of an ActiveRecord::Base # instance. def with_transaction_returning_status: () { () -> untyped } -> untyped def trigger_transactional_callbacks?: () -> untyped attr_reader _committed_already_called: untyped attr_reader _trigger_update_callback: untyped attr_reader _trigger_destroy_callback: untyped # Save the new record state and id of a record so it can be restored later if a transaction fails. def remember_transaction_record_state: () -> untyped # Clear the new record state and id of a record. def clear_transaction_record_state: () -> (nil | untyped) # Force to clear the transaction record state. def force_clear_transaction_record_state: () -> untyped # Restore the new record state and id of a record that was previously saved by a call to save_record_state. def restore_transaction_record_state: (?bool force_restore_state) -> untyped # Determine if a transaction included an action for :create, :update, or :destroy. Used in filtering callbacks. def transaction_include_any_action?: (untyped actions) -> untyped # Add the record to the current transaction so that the #after_rollback and #after_commit # callbacks can be called. def add_to_transaction: () -> untyped def has_transactional_callbacks?: () -> untyped # Updates the attributes on this particular Active Record object so that # if it's associated with a transaction, then the state of the Active Record # object will be updated to reflect the current state of the transaction. # # The @transaction_state variable stores the states of the associated # transaction. This relies on the fact that a transaction can only be in # one rollback or commit (otherwise a list of states would be required). # Each Active Record object inside of a transaction carries that transaction's # TransactionState. # # This method checks to see if the ActiveRecord object's state reflects # the TransactionState, and rolls back or commits the Active Record object # as appropriate. def sync_with_transaction_state: () -> untyped end end module ActiveRecord module Translation include ActiveModel::Translation def lookup_ancestors: () -> untyped def i18n_scope: () -> :activerecord end end module ActiveRecord # :stopdoc: module Type class AdapterSpecificRegistry < ActiveModel::Type::Registry def add_modifier: (untyped options, untyped klass, **untyped args) -> untyped def registration_klass: () -> untyped def find_registration: (untyped symbol, *untyped args, **untyped kwargs) -> untyped end class Registration def initialize: (untyped name, untyped block, ?override: untyped? override, ?adapter: untyped? adapter) -> untyped def call: (untyped _registry, *untyped args, ?adapter: untyped? adapter, **untyped kwargs) -> untyped def matches?: (untyped type_name, *untyped args, **untyped kwargs) -> untyped def <=>: (untyped other) -> untyped attr_reader name: untyped attr_reader block: untyped attr_reader adapter: untyped attr_reader override: untyped def priority: () -> untyped def priority_except_adapter: () -> untyped def matches_adapter?: (?adapter: untyped? adapter) -> untyped def conflicts_with?: (untyped other) -> untyped def same_priority_except_adapter?: (untyped other) -> untyped def has_adapter_conflict?: (untyped other) -> untyped end class DecorationRegistration < Registration def initialize: (untyped options, untyped klass, ?adapter: untyped? adapter) -> untyped def call: (untyped registry, *untyped args, **untyped kwargs) -> untyped def matches?: (*untyped args, **untyped kwargs) -> untyped def priority: () -> untyped attr_reader options: untyped attr_reader klass: untyped def matches_options?: (**untyped kwargs) -> untyped end end class TypeConflictError < StandardError end end module ActiveRecord module TypeCaster class Connection # :nodoc: def initialize: (untyped klass, untyped table_name) -> untyped def type_cast_for_database: (untyped attr_name, untyped value) -> untyped def type_for_attribute: (untyped attr_name) -> untyped attr_reader table_name: untyped end end end module ActiveRecord module TypeCaster class Map # :nodoc: def initialize: (untyped types) -> untyped def type_cast_for_database: (untyped attr_name, untyped value) -> untyped attr_reader types: untyped end end end module ActiveRecord module TypeCaster end end module ActiveRecord module Type class Date < ActiveModel::Type::Date include Internal::Timezone end end end module ActiveRecord module Type class DateTime < ActiveModel::Type::DateTime include Internal::Timezone end end end module ActiveRecord module Type class DecimalWithoutScale < ActiveModel::Type::BigInteger # :nodoc: def `type`: () -> :decimal def type_cast_for_schema: (untyped value) -> untyped end end end module ActiveRecord module Type class HashLookupTypeMap < TypeMap # :nodoc: def alias_type: (untyped `type`, untyped alias_type) -> untyped def key?: (untyped key) -> untyped def keys: () -> untyped def perform_fetch: (untyped `type`, *untyped args) { () -> untyped } -> untyped end end end module ActiveRecord module Type module Internal module Timezone def is_utc?: () -> untyped def default_timezone: () -> untyped end end end end module ActiveRecord module Type class Json < ActiveModel::Type::Value include ActiveModel::Type::Helpers::Mutable def `type`: () -> :json def deserialize: (untyped value) -> untyped def serialize: (untyped value) -> untyped def changed_in_place?: (untyped raw_old_value, untyped new_value) -> untyped def accessor: () -> untyped end end end module ActiveRecord module Type attr_accessor registry: untyped # Add a new type to the registry, allowing it to be referenced as a # symbol by {ActiveRecord::Base.attribute}[rdoc-ref:Attributes::ClassMethods#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. def self.register: (untyped type_name, ?untyped? klass, **untyped options) { () -> untyped } -> untyped def self.lookup: (*untyped args, ?adapter: untyped adapter, **untyped kwargs) -> untyped def self.default_value: () -> untyped def self.current_adapter_name: () -> untyped BigInteger: untyped Binary: untyped Boolean: untyped Decimal: untyped Float: untyped Integer: untyped String: untyped Value: untyped end end module ActiveRecord module Type # Note: It inherits unnamed class, but omitted class Serialized include ActiveModel::Type::Helpers::Mutable attr_reader subtype: untyped attr_reader coder: untyped def initialize: (untyped subtype, untyped coder) -> untyped def deserialize: (untyped value) -> untyped def serialize: (untyped value) -> (nil | untyped) def inspect: () -> untyped def changed_in_place?: (untyped raw_old_value, untyped value) -> (::FalseClass | untyped) def accessor: () -> untyped def assert_valid_value: (untyped value) -> untyped def force_equality?: (untyped value) -> untyped def default_value?: (untyped value) -> untyped def encoded: (untyped value) -> untyped end end end module ActiveRecord module Type class Text < ActiveModel::Type::String # :nodoc: def `type`: () -> :text end end end module ActiveRecord module Type class Time < ActiveModel::Type::Time include Internal::Timezone # Note: It inherits unnamed class, but omitted class Value end def serialize: (untyped value) -> untyped end end end module ActiveRecord module Type class TypeMap # :nodoc: def initialize: () -> untyped def lookup: (untyped lookup_key, *untyped args) -> untyped def fetch: (untyped lookup_key, *untyped args) { () -> untyped } -> untyped def register_type: (untyped key, ?untyped? value) { () -> untyped } -> untyped def alias_type: (untyped key, untyped target_key) -> untyped def clear: () -> untyped def perform_fetch: (untyped lookup_key, *untyped args) { (untyped, untyped) -> untyped } -> untyped end end end module ActiveRecord module Type class UnsignedInteger < ActiveModel::Type::Integer def max_value: () -> untyped def min_value: () -> 0 end end end module ActiveRecord module Validations extend ::ActiveModel::Validations::ClassMethods class AbsenceValidator < ActiveModel::Validations::AbsenceValidator # :nodoc: def validate_each: (untyped record, untyped attribute, untyped association_or_value) -> untyped end module ClassMethods # 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. def validates_absence_of: (*untyped attr_names) -> untyped end end end module ActiveRecord module Validations class AssociatedValidator < ActiveModel::EachValidator # nodoc: def validate_each: (untyped record, untyped attribute, untyped value) -> untyped def valid_object?: (untyped record) -> untyped end module ClassMethods # 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}[rdoc-ref:Validations::ClassMethods#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. def validates_associated: (*untyped attr_names) -> untyped end end end module ActiveRecord module Validations class LengthValidator < ActiveModel::Validations::LengthValidator # :nodoc: def validate_each: (untyped record, untyped attribute, untyped association_or_value) -> untyped end module ClassMethods # 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. def validates_length_of: (*untyped attr_names) -> untyped end end end module ActiveRecord module Validations class PresenceValidator < ActiveModel::Validations::PresenceValidator # :nodoc: def validate_each: (untyped record, untyped attribute, untyped association_or_value) -> untyped end module ClassMethods # 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}[rdoc-ref:Validations::ClassMethods#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. def validates_presence_of: (*untyped attr_names) -> untyped end end end module ActiveRecord # = Active Record \RecordInvalid # # Raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and # {ActiveRecord::Base#create!}[rdoc-ref:Persistence::ClassMethods#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 class RecordInvalid < ActiveRecordError attr_reader record: untyped def initialize: (?untyped? record) -> untyped end # = 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?}[rdoc-ref:Persistence#new_record?]. module Validations extend ActiveSupport::Concern include ActiveModel::Validations # 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}[rdoc-ref:Persistence#save] method is replaced # with this when the validations module is mixed in, which it is by default. def save: (**untyped options) -> untyped # Attempts to save the record just like {ActiveRecord::Base#save}[rdoc-ref:Base#save] but # will raise an ActiveRecord::RecordInvalid exception instead of returning +false+ if the record is not valid. def save!: (**untyped options) -> untyped # 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?}[rdoc-ref:Persistence#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. def valid?: (?untyped? context) -> untyped def default_validation_context: () -> untyped def raise_validation_error: () -> untyped def perform_validations: (?::Hash[untyped, untyped] options) -> untyped end end module ActiveRecord module Validations class UniquenessValidator < ActiveModel::EachValidator # :nodoc: def initialize: (untyped options) -> untyped def validate_each: (untyped record, untyped attribute, untyped value) -> untyped # The check for an existing value should be run from a class that # isn't abstract. This means working down from the current class # (self), to the first non-abstract class. Since classes don't know # their subclasses, we have to build the hierarchy between self and # the record's class. def find_finder_class_for: (untyped record) -> untyped def build_relation: (untyped klass, untyped attribute, untyped value) -> untyped def scope_relation: (untyped record, untyped relation) -> untyped def map_enum_attribute: (untyped klass, untyped attribute, untyped value) -> untyped end module ClassMethods # 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 # # 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 (+true+ by default). # * :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}[rdoc-ref:Persistence#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}[rdoc-ref:ConnectionAdapters::SchemaStatements#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}[rdoc-ref:Persistence#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}[https://en.wikipedia.org/wiki/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: # # * ActiveRecord::ConnectionAdapters::Mysql2Adapter. # * ActiveRecord::ConnectionAdapters::SQLite3Adapter. # * ActiveRecord::ConnectionAdapters::PostgreSQLAdapter. def validates_uniqueness_of: (*untyped attr_names) -> untyped end end end module ActiveRecord # Returns the version of the currently loaded ActiveRecord as a Gem::Version def self.version: () -> untyped end module Arel # :nodoc: all module AliasPredication def as: (untyped other) -> untyped end end module Arel # :nodoc: all module Attributes # Note: It inherits unnamed class, but omitted class Attribute include Arel::Expressions include Arel::Predications include Arel::AliasPredication include Arel::OrderPredications include Arel::Math # # # Create a node for lowering this attribute def lower: () -> untyped def type_cast_for_database: (untyped value) -> untyped def able_to_type_cast?: () -> untyped end class String < Attribute end class Time < Attribute end class Boolean < Attribute end class Decimal < Attribute end class Float < Attribute end class Integer < Attribute end class Undefined < Attribute end end Attribute: untyped end module Arel # :nodoc: all module Attributes # # # Factory method to wrap a raw database +column+ to an Arel Attribute. def self.for: (untyped column) -> untyped end end module Arel # :nodoc: all module Collectors class Bind def initialize: () -> untyped def <<: (untyped str) -> untyped def add_bind: (untyped bind) -> untyped def value: () -> untyped end end end module Arel # :nodoc: all module Collectors class Composite def initialize: (untyped left, untyped right) -> untyped def <<: (untyped str) -> untyped def add_bind: (untyped bind) { () -> untyped } -> untyped def value: () -> ::Array[untyped] attr_reader left: untyped attr_reader right: untyped end end end module Arel # :nodoc: all module Collectors class PlainString def initialize: () -> untyped def value: () -> untyped def <<: (untyped str) -> untyped end end end module Arel # :nodoc: all module Collectors class SQLString < PlainString def initialize: () -> untyped def add_bind: (untyped bind) { (untyped) -> untyped } -> untyped end end end module Arel # :nodoc: all module Collectors class SubstituteBinds def initialize: (untyped quoter, untyped delegate_collector) -> untyped def <<: (untyped str) -> untyped def add_bind: (untyped bind) -> untyped def value: () -> untyped attr_reader quoter: untyped attr_reader delegate: untyped end end end module Arel # :nodoc: all # # # FIXME hopefully we can remove this module Crud def compile_update: (untyped values, untyped pk) -> untyped def compile_insert: (untyped values) -> untyped def create_insert: () -> InsertManager def compile_delete: () -> untyped end end module Arel # :nodoc: all class DeleteManager < Arel::TreeManager include TreeManager::StatementMethods def initialize: () -> untyped def from: (untyped relation) -> untyped end end module Arel # :nodoc: all class ArelError < StandardError end class EmptyJoinError < ArelError end end module Arel # :nodoc: all module Expressions def count: (?bool distinct) -> Nodes::Count def sum: () -> Nodes::Sum def maximum: () -> Nodes::Max def minimum: () -> Nodes::Min def average: () -> Nodes::Avg def extract: (untyped field) -> Nodes::Extract end end module Arel # :nodoc: all # # # Methods for creating various nodes module FactoryMethods def create_true: () -> Arel::Nodes::True def create_false: () -> Arel::Nodes::False def create_table_alias: (untyped relation, untyped name) -> Nodes::TableAlias def create_join: (untyped to, ?untyped? constraint, ?untyped klass) -> untyped def create_string_join: (untyped to) -> untyped def create_and: (untyped clauses) -> Nodes::And def create_on: (untyped expr) -> Nodes::On def grouping: (untyped expr) -> Nodes::Grouping # # # Create a LOWER() function def lower: (untyped column) -> Nodes::NamedFunction def coalesce: (*untyped exprs) -> Nodes::NamedFunction end end module Arel # :nodoc: all class InsertManager < Arel::TreeManager def initialize: () -> untyped def into: (untyped table) -> untyped def columns: () -> untyped def values=: (untyped val) -> untyped def select: (untyped select) -> untyped def insert: (untyped fields) -> (nil | untyped) def create_values: (untyped values) -> Nodes::ValuesList def create_values_list: (untyped rows) -> Nodes::ValuesList end end module Arel # :nodoc: all module Math def *: (untyped other) -> Arel::Nodes::Multiplication def +: (untyped other) -> Arel::Nodes::Grouping def -: (untyped other) -> Arel::Nodes::Grouping def /: (untyped other) -> Arel::Nodes::Division def &: (untyped other) -> Arel::Nodes::Grouping def |: (untyped other) -> Arel::Nodes::Grouping def ^: (untyped other) -> Arel::Nodes::Grouping def <<: (untyped other) -> Arel::Nodes::Grouping def >>: (untyped other) -> Arel::Nodes::Grouping def ~: () -> Arel::Nodes::BitwiseNot end end module Arel # :nodoc: all module Nodes class And < Arel::Nodes::NodeExpression attr_reader children: untyped def initialize: (untyped children) -> untyped def left: () -> untyped def right: () -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class Ascending < Ordering def reverse: () -> Descending def direction: () -> :asc def ascending?: () -> ::TrueClass def descending?: () -> ::FalseClass end end end module Arel # :nodoc: all module Nodes class Binary < Arel::Nodes::NodeExpression attr_accessor left: untyped attr_accessor right: untyped def initialize: (untyped left, untyped right) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class BindParam < Node attr_reader value: untyped def initialize: (untyped value) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped def nil?: () -> untyped def infinite?: () -> untyped def unboundable?: () -> untyped end end end module Arel # :nodoc: all module Nodes class Case < Arel::Nodes::NodeExpression attr_accessor case: untyped attr_accessor conditions: untyped attr_accessor default: untyped def initialize: (?untyped? expression, ?untyped? default) -> untyped def when: (untyped condition, ?untyped? expression) -> untyped def then: (untyped expression) -> untyped def else: (untyped expression) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end class When < Binary end class Else < Unary end end end module Arel # :nodoc: all module Nodes class Casted < Arel::Nodes::NodeExpression # :nodoc: attr_reader val: untyped # :nodoc: attr_reader attribute: untyped def initialize: (untyped val, untyped attribute) -> untyped def nil?: () -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end class Quoted < Arel::Nodes::Unary def nil?: () -> untyped def infinite?: () -> untyped end def self.build_quoted: (untyped other, ?untyped? attribute) -> untyped end end module Arel # :nodoc: all module Nodes class Comment < Arel::Nodes::Node attr_reader values: untyped def initialize: (untyped values) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class Count < Arel::Nodes::Function def initialize: (untyped expr, ?bool distinct, ?untyped? aliaz) -> untyped end end end module Arel # :nodoc: all module Nodes class DeleteStatement < Arel::Nodes::Node attr_accessor left: untyped attr_accessor right: untyped attr_accessor orders: untyped attr_accessor limit: untyped attr_accessor offset: untyped attr_accessor key: untyped def initialize: (?untyped? relation, ?untyped wheres) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class Descending < Ordering def reverse: () -> Ascending def direction: () -> :desc def ascending?: () -> ::FalseClass def descending?: () -> ::TrueClass end end end module Arel # :nodoc: all module Nodes class Equality < Arel::Nodes::Binary def operator: () -> Symbol end end end module Arel # :nodoc: all module Nodes class Extract < Arel::Nodes::Unary attr_accessor field: untyped def initialize: (untyped expr, untyped field) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class False < Arel::Nodes::NodeExpression def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class FullOuterJoin < Arel::Nodes::Join end end end module Arel # :nodoc: all module Nodes class Function < Arel::Nodes::NodeExpression include Arel::WindowPredications attr_accessor expressions: untyped attr_accessor alias: untyped attr_accessor distinct: untyped def initialize: (untyped expr, ?untyped? aliaz) -> untyped def as: (untyped aliaz) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class Grouping < Unary end end end module Arel # :nodoc: all module Nodes class InfixOperation < Binary include Arel::Expressions include Arel::Predications include Arel::OrderPredications include Arel::AliasPredication include Arel::Math attr_reader operator: untyped def initialize: (untyped operator, untyped left, untyped right) -> untyped end class Multiplication < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class Division < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class Addition < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class Subtraction < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class Concat < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class BitwiseAnd < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class BitwiseOr < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class BitwiseXor < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class BitwiseShiftLeft < InfixOperation def initialize: (untyped left, untyped right) -> untyped end class BitwiseShiftRight < InfixOperation def initialize: (untyped left, untyped right) -> untyped end end end module Arel # :nodoc: all module Nodes class InnerJoin < Arel::Nodes::Join end end end module Arel # :nodoc: all module Nodes class In < Equality end end end module Arel # :nodoc: all module Nodes class InsertStatement < Arel::Nodes::Node attr_accessor relation: untyped attr_accessor columns: untyped attr_accessor values: untyped attr_accessor select: untyped def initialize: () -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class JoinSource < Arel::Nodes::Binary def initialize: (untyped single_source, ?untyped joinop) -> untyped def empty?: () -> untyped end end end module Arel # :nodoc: all module Nodes class Matches < Binary attr_reader escape: untyped attr_accessor case_sensitive: untyped def initialize: (untyped left, untyped right, ?untyped? escape, ?bool case_sensitive) -> untyped end class DoesNotMatch < Matches end end end module Arel # :nodoc: all module Nodes class NamedFunction < Arel::Nodes::Function attr_accessor name: untyped def initialize: (untyped name, untyped expr, ?untyped? aliaz) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class NodeExpression < Arel::Nodes::Node include Arel::Expressions include Arel::Predications include Arel::AliasPredication include Arel::OrderPredications include Arel::Math end end end module Arel # :nodoc: all module Nodes # # # Abstract base class for all AST nodes class Node include Arel::FactoryMethods include Enumerable[untyped, untyped] # # # Factory method to create a Nodes::Not node that has the recipient of # the caller as a child. def not: () -> Nodes::Not # # # Factory method to create a Nodes::Grouping node that has an Nodes::Or # node as a child. def or: (untyped right) -> Nodes::Grouping # # # Factory method to create an Nodes::And node. def and: (untyped right) -> Nodes::And # FIXME: this method should go away. I don't like people calling # to_sql on non-head nodes. This forces us to walk the AST until we # can find a node that has a "relation" member. # # Maybe we should just use `Table.engine`? :'( def to_sql: (?untyped engine) -> untyped # Iterate through AST, nodes will be yielded depth-first def each: () { () -> untyped } -> untyped end end end module Arel # :nodoc: all module Nodes class OuterJoin < Arel::Nodes::Join end end end module Arel # :nodoc: all module Nodes class Over < Binary include Arel::AliasPredication def initialize: (untyped left, ?untyped? right) -> untyped def operator: () -> "OVER" end end end module Arel # :nodoc: all module Nodes class Regexp < Binary attr_accessor case_sensitive: untyped def initialize: (untyped left, untyped right, ?bool case_sensitive) -> untyped end class NotRegexp < Regexp end end end module Arel # :nodoc: all module Nodes class RightOuterJoin < Arel::Nodes::Join end end end module Arel # :nodoc: all module Nodes class SelectCore < Arel::Nodes::Node attr_accessor projections: untyped attr_accessor wheres: untyped attr_accessor groups: untyped attr_accessor windows: untyped attr_accessor comment: untyped attr_accessor havings: untyped attr_accessor source: untyped attr_accessor set_quantifier: untyped attr_accessor optimizer_hints: untyped def initialize: () -> untyped def from: () -> untyped def from=: (untyped value) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class SelectStatement < Arel::Nodes::NodeExpression attr_reader cores: untyped attr_accessor limit: untyped attr_accessor orders: untyped attr_accessor lock: untyped attr_accessor offset: untyped attr_accessor with: untyped def initialize: (?::Array[untyped] cores) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class SqlLiteral < String include Arel::Expressions include Arel::Predications include Arel::AliasPredication include Arel::OrderPredications def encode_with: (untyped coder) -> untyped end end end module Arel # :nodoc: all module Nodes class StringJoin < Arel::Nodes::Join def initialize: (untyped left, ?untyped? right) -> untyped end end end module Arel # :nodoc: all module Nodes class TableAlias < Arel::Nodes::Binary def []: (untyped name) -> ::Arel::Attributes::Attribute def table_name: () -> untyped def type_cast_for_database: (*untyped args) -> untyped def able_to_type_cast?: () -> untyped end end end module Arel # :nodoc: all module Nodes class Distinct < Arel::Nodes::NodeExpression def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class True < Arel::Nodes::NodeExpression def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class UnaryOperation < Unary attr_reader operator: untyped def initialize: (untyped operator, untyped operand) -> untyped end class BitwiseNot < UnaryOperation def initialize: (untyped operand) -> untyped end end end module Arel # :nodoc: all module Nodes class Unary < Arel::Nodes::NodeExpression attr_accessor expr: untyped def initialize: (untyped expr) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class UnqualifiedColumn < Arel::Nodes::Unary def relation: () -> untyped def column: () -> untyped def name: () -> untyped end end end module Arel # :nodoc: all module Nodes class UpdateStatement < Arel::Nodes::Node attr_accessor relation: untyped attr_accessor wheres: untyped attr_accessor values: untyped attr_accessor orders: untyped attr_accessor limit: untyped attr_accessor offset: untyped attr_accessor key: untyped def initialize: () -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end end end module Arel # :nodoc: all module Nodes class ValuesList < Unary end end end module Arel # :nodoc: all module Nodes class Window < Arel::Nodes::Node attr_accessor orders: untyped attr_accessor framing: untyped attr_accessor partitions: untyped def initialize: () -> untyped def order: (*untyped expr) -> untyped def partition: (*untyped expr) -> untyped def frame: (untyped expr) -> untyped def rows: (?untyped? expr) -> untyped def range: (?untyped? expr) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end class NamedWindow < Window attr_accessor name: untyped def initialize: (untyped name) -> untyped def initialize_copy: (untyped other) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped end class Rows < Unary def initialize: (?untyped? expr) -> untyped end class Range[Elem] < Unary def initialize: (?untyped? expr) -> untyped end class CurrentRow < Node def hash: () -> untyped def eql?: (untyped other) -> untyped end class Preceding < Unary def initialize: (?untyped? expr) -> untyped end class Following < Unary def initialize: (?untyped? expr) -> untyped end end end module Arel # :nodoc: all module Nodes class With < Arel::Nodes::Unary end class WithRecursive < With end end end module Arel # :nodoc: all module OrderPredications def asc: () -> Nodes::Ascending def desc: () -> Nodes::Descending end end module Arel # :nodoc: all module Predications def not_eq: (untyped other) -> Nodes::NotEqual def not_eq_any: (untyped others) -> untyped def not_eq_all: (untyped others) -> untyped def eq: (untyped other) -> Nodes::Equality def is_not_distinct_from: (untyped other) -> Nodes::IsNotDistinctFrom def is_distinct_from: (untyped other) -> Nodes::IsDistinctFrom def eq_any: (untyped others) -> untyped def eq_all: (untyped others) -> untyped def between: (untyped other) -> untyped def `in`: (untyped other) -> untyped def in_any: (untyped others) -> untyped def in_all: (untyped others) -> untyped def not_between: (untyped other) -> untyped def not_in: (untyped other) -> untyped def not_in_any: (untyped others) -> untyped def not_in_all: (untyped others) -> untyped def matches: (untyped other, ?untyped? escape, ?bool case_sensitive) -> Nodes::Matches def matches_regexp: (untyped other, ?bool case_sensitive) -> Nodes::Regexp def matches_any: (untyped others, ?untyped? escape, ?bool case_sensitive) -> untyped def matches_all: (untyped others, ?untyped? escape, ?bool case_sensitive) -> untyped def does_not_match: (untyped other, ?untyped? escape, ?bool case_sensitive) -> Nodes::DoesNotMatch def does_not_match_regexp: (untyped other, ?bool case_sensitive) -> Nodes::NotRegexp def does_not_match_any: (untyped others, ?untyped? escape) -> untyped def does_not_match_all: (untyped others, ?untyped? escape) -> untyped def gteq: (untyped right) -> Nodes::GreaterThanOrEqual def gteq_any: (untyped others) -> untyped def gteq_all: (untyped others) -> untyped def gt: (untyped right) -> Nodes::GreaterThan def gt_any: (untyped others) -> untyped def gt_all: (untyped others) -> untyped def lt: (untyped right) -> Nodes::LessThan def lt_any: (untyped others) -> untyped def lt_all: (untyped others) -> untyped def lteq: (untyped right) -> Nodes::LessThanOrEqual def lteq_any: (untyped others) -> untyped def lteq_all: (untyped others) -> untyped def when: (untyped right) -> untyped def concat: (untyped other) -> Nodes::Concat def grouping_any: (untyped method_id, untyped others, *untyped extras) -> Nodes::Grouping def grouping_all: (untyped method_id, untyped others, *untyped extras) -> Nodes::Grouping def quoted_node: (untyped other) -> untyped def quoted_array: (untyped others) -> untyped def infinity?: (untyped value) -> untyped def unboundable?: (untyped value) -> untyped def open_ended?: (untyped value) -> untyped end end module Arel VERSION: ::String # Wrap a known-safe SQL string for passing to query methods, e.g. # # Post.order(Arel.sql("length(title)")).last # # 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. def self.sql: (untyped raw_sql) -> Arel::Nodes::SqlLiteral def self.star: () -> untyped def self.arel_node?: (untyped value) -> untyped def self.fetch_attribute: (untyped value) { (untyped) -> untyped } -> untyped Node: untyped end module Arel # :nodoc: all class SelectManager < Arel::TreeManager include Arel::Crud STRING_OR_SYMBOL_CLASS: ::Array[untyped] def initialize: (?untyped? table) -> untyped def initialize_copy: (untyped other) -> untyped def limit: () -> untyped def constraints: () -> untyped def offset: () -> untyped def skip: (untyped amount) -> untyped # # # Produces an Arel::Nodes::Exists node def exists: () -> Arel::Nodes::Exists def as: (untyped other) -> untyped def lock: (?untyped locking) -> untyped def locked: () -> untyped def on: (*untyped exprs) -> untyped def group: (*untyped columns) -> untyped def from: (untyped table) -> untyped def froms: () -> untyped def join: (untyped relation, ?untyped klass) -> untyped def outer_join: (untyped relation) -> untyped def having: (untyped expr) -> untyped def window: (untyped name) -> untyped def project: (*untyped projections) -> untyped def projections: () -> untyped def projections=: (untyped projections) -> untyped def optimizer_hints: (*untyped hints) -> untyped def distinct: (?bool value) -> untyped def distinct_on: (untyped value) -> untyped def order: (*untyped expr) -> untyped def orders: () -> untyped def where_sql: (?untyped engine) -> (nil | Nodes::SqlLiteral) def union: (untyped operation, ?untyped? other) -> untyped def intersect: (untyped other) -> Nodes::Intersect def except: (untyped other) -> Nodes::Except def lateral: (?untyped? table_name) -> Nodes::Lateral def with: (*untyped subqueries) -> untyped def take: (untyped limit) -> untyped def join_sources: () -> untyped def source: () -> untyped def comment: (*untyped values) -> untyped def collapse: (untyped exprs) -> untyped end end module Arel # :nodoc: all class Table include Arel::Crud include Arel::FactoryMethods attr_accessor engine: untyped attr_accessor name: untyped attr_accessor table_alias: untyped def initialize: (untyped name, ?type_caster: untyped? type_caster, ?as: untyped? as) -> untyped def `alias`: (?::String name) -> Nodes::TableAlias def from: () -> SelectManager def join: (untyped relation, ?untyped klass) -> untyped def outer_join: (untyped relation) -> untyped def group: (*untyped columns) -> untyped def order: (*untyped expr) -> untyped def where: (untyped condition) -> untyped def project: (*untyped things) -> untyped def take: (untyped amount) -> untyped def skip: (untyped amount) -> untyped def having: (untyped expr) -> untyped def []: (untyped name) -> untyped def hash: () -> untyped def eql?: (untyped other) -> untyped def type_cast_for_database: (untyped attribute_name, untyped value) -> untyped def able_to_type_cast?: () -> untyped attr_reader type_caster: untyped end end module Arel # :nodoc: all class TreeManager include Arel::FactoryMethods module StatementMethods def take: (untyped limit) -> untyped def offset: (untyped offset) -> untyped def order: (*untyped expr) -> untyped def key=: (untyped key) -> untyped def key: () -> untyped def wheres=: (untyped exprs) -> untyped def where: (untyped expr) -> untyped end attr_reader ast: untyped def initialize: () -> untyped def to_dot: () -> untyped def to_sql: (?untyped engine) -> untyped def initialize_copy: (untyped other) -> untyped def where: (untyped expr) -> untyped end end module Arel # :nodoc: all class UpdateManager < Arel::TreeManager include TreeManager::StatementMethods def initialize: () -> untyped # # # UPDATE +table+ def table: (untyped table) -> untyped def set: (untyped values) -> untyped end end module Arel # :nodoc: all module Visitors class DepthFirst < Arel::Visitors::Visitor def initialize: (?untyped? block) -> untyped def visit: (untyped o, ?untyped? _) -> untyped def unary: (untyped o) -> untyped def function: (untyped o) -> untyped def visit_Arel_Nodes_NamedFunction: (untyped o) -> untyped def visit_Arel_Nodes_Count: (untyped o) -> untyped def visit_Arel_Nodes_Case: (untyped o) -> untyped def nary: (untyped o) -> untyped def binary: (untyped o) -> untyped def visit_Arel_Nodes_StringJoin: (untyped o) -> untyped def visit_Arel_Attribute: (untyped o) -> untyped def visit_Arel_Table: (untyped o) -> untyped def terminal: (untyped o) -> nil def visit_Arel_Nodes_InsertStatement: (untyped o) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o) -> untyped def visit_Arel_Nodes_SelectStatement: (untyped o) -> untyped def visit_Arel_Nodes_UpdateStatement: (untyped o) -> untyped def visit_Arel_Nodes_Comment: (untyped o) -> untyped def visit_Array: (untyped o) -> untyped def visit_Hash: (untyped o) -> untyped DISPATCH: untyped def get_dispatch_cache: () -> untyped end end end module Arel # :nodoc: all module Visitors class Dot < Arel::Visitors::Visitor class Node # :nodoc: attr_accessor name: untyped # :nodoc: attr_accessor id: untyped # :nodoc: attr_accessor fields: untyped def initialize: (untyped name, untyped id, ?untyped fields) -> untyped end # Note: It inherits unnamed class, but omitted class Edge end def initialize: () -> untyped def accept: (untyped object, untyped collector) -> untyped def visit_Arel_Nodes_Ordering: (untyped o) -> untyped def visit_Arel_Nodes_TableAlias: (untyped o) -> untyped def visit_Arel_Nodes_Count: (untyped o) -> untyped def visit_Arel_Nodes_ValuesList: (untyped o) -> untyped def visit_Arel_Nodes_StringJoin: (untyped o) -> untyped def visit_Arel_Nodes_InnerJoin: (untyped o) -> untyped def visit_Arel_Nodes_DeleteStatement: (untyped o) -> untyped def unary: (untyped o) -> untyped def window: (untyped o) -> untyped def named_window: (untyped o) -> untyped def function: (untyped o) -> untyped def extract: (untyped o) -> untyped def visit_Arel_Nodes_NamedFunction: (untyped o) -> untyped def visit_Arel_Nodes_InsertStatement: (untyped o) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o) -> untyped def visit_Arel_Nodes_SelectStatement: (untyped o) -> untyped def visit_Arel_Nodes_UpdateStatement: (untyped o) -> untyped def visit_Arel_Table: (untyped o) -> untyped def visit_Arel_Nodes_Casted: (untyped o) -> untyped def visit_Arel_Attribute: (untyped o) -> untyped def nary: (untyped o) -> untyped def binary: (untyped o) -> untyped def visit_String: (untyped o) -> untyped def visit_Arel_Nodes_BindParam: (untyped o) -> nil def visit_Hash: (untyped o) -> untyped def visit_Array: (untyped o) -> untyped def visit_Arel_Nodes_Comment: (untyped o) -> untyped def visit_edge: (untyped o, untyped method) -> untyped def visit: (untyped o) -> (nil | untyped) def edge: (untyped name) { () -> untyped } -> untyped def with_node: (untyped node) { () -> untyped } -> untyped def quote: (untyped string) -> untyped def to_dot: () -> untyped end end end module Arel # :nodoc: all module Visitors class IBM_DB < Arel::Visitors::ToSql def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_OptimizerHints: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Limit: (untyped o, untyped collector) -> untyped def is_distinct_from: (untyped o, untyped collector) -> untyped def collect_optimizer_hints: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class Informix < Arel::Visitors::ToSql def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_OptimizerHints: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Offset: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Limit: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class MSSQL < Arel::Visitors::ToSql class RowNumber < ::Struct[untyped] attr_accessor children(): untyped end def initialize: () -> untyped def visit_Arel_Nodes_IsNotDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Visitors_MSSQL_RowNumber: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_OptimizerHints: (untyped o, untyped collector) -> untyped def get_offset_limit_clause: (untyped o) -> untyped def visit_Arel_Nodes_DeleteStatement: (untyped o, untyped collector) -> untyped def collect_optimizer_hints: (untyped o, untyped collector) -> untyped def determine_order_by: (untyped orders, untyped x) -> untyped def row_num_literal: (untyped order_by) -> RowNumber def select_count?: (untyped x) -> untyped # FIXME raise exception of there is no pk? def find_left_table_pk: (untyped o) -> untyped def find_primary_key: (untyped o) -> untyped end end end module Arel # :nodoc: all module Visitors class MySQL < Arel::Visitors::ToSql def visit_Arel_Nodes_Bin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UnqualifiedColumn: (untyped o, untyped collector) -> untyped # # # :'( # http://dev.mysql.com/doc/refman/5.0/en/select.html#id3482214 def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Concat: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsNotDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsDistinctFrom: (untyped o, untyped collector) -> untyped # In the simple case, MySQL allows us to place JOINs directly into the UPDATE # query. However, this does not allow for LIMIT, OFFSET and ORDER. To support # these, we must use a subquery. def prepare_update_statement: (untyped o) -> untyped # MySQL is too stupid to create a temporary table for use subquery, so we have # to give it some prompting in the form of a subsubquery. def build_subselect: (untyped key, untyped o) -> untyped end end end module Arel # :nodoc: all module Visitors class Oracle12 < Arel::Visitors::ToSql def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectOptions: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Limit: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Offset: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Except: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UpdateStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_BindParam: (untyped o, untyped collector) -> untyped def is_distinct_from: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class Oracle < Arel::Visitors::ToSql def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Limit: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Offset: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Except: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UpdateStatement: (untyped o, untyped collector) -> untyped # # # Hacks for the order clauses specific to Oracle def order_hacks: (untyped o) -> untyped # Split string by commas but count opening and closing brackets # and ignore commas inside brackets. def split_order_string: (untyped string) -> untyped def visit_Arel_Nodes_BindParam: (untyped o, untyped collector) -> untyped def is_distinct_from: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class PostgreSQL < Arel::Visitors::ToSql def visit_Arel_Nodes_Matches: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_DoesNotMatch: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Regexp: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NotRegexp: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_DistinctOn: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_BindParam: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_GroupingElement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Cube: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_RollUp: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_GroupingSet: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Lateral: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsNotDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsDistinctFrom: (untyped o, untyped collector) -> untyped # Used by Lateral visitor to enclose select queries in parentheses def grouping_parentheses: (untyped o, untyped collector) -> untyped # Utilized by GroupingSet, Cube & RollUp visitors to # handle grouping aggregation semantics def grouping_array_or_grouping_element: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors end end module Arel # :nodoc: all module Visitors class SQLite < Arel::Visitors::ToSql # Locks are not supported in SQLite def visit_Arel_Nodes_Lock: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_True: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_False: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsNotDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsDistinctFrom: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class UnsupportedVisitError < StandardError def initialize: (untyped object) -> untyped end class ToSql < Arel::Visitors::Visitor def initialize: (untyped connection) -> untyped def compile: (untyped node, ?untyped collector) -> untyped def visit_Arel_Nodes_DeleteStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UpdateStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_InsertStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Exists: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Casted: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Quoted: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_True: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_False: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_ValuesList: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectStatement: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectOptions: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_OptimizerHints: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Comment: (untyped o, untyped collector) -> untyped def collect_nodes_for: (untyped nodes, untyped collector, untyped spacer, ?::String connector) -> untyped def visit_Arel_Nodes_Bin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Distinct: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_DistinctOn: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_With: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_WithRecursive: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Union: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UnionAll: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Intersect: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Except: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NamedWindow: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Window: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Rows: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Range: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Preceding: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Following: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_CurrentRow: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Over: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Offset: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Limit: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Lock: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Grouping: (untyped o, untyped collector) -> untyped def visit_Arel_SelectManager: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Ascending: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Descending: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Group: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NamedFunction: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Extract: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Count: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Sum: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Max: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Min: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Avg: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_TableAlias: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Between: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_GreaterThanOrEqual: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_GreaterThan: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_LessThanOrEqual: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_LessThan: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Matches: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_DoesNotMatch: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_JoinSource: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Regexp: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NotRegexp: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_StringJoin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_FullOuterJoin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_OuterJoin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_RightOuterJoin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_InnerJoin: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_On: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Not: (untyped o, untyped collector) -> untyped def visit_Arel_Table: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_In: (untyped o, untyped collector) -> untyped def collect_in_clause: (untyped left, untyped right, untyped collector) -> untyped def visit_Arel_Nodes_NotIn: (untyped o, untyped collector) -> untyped def collect_not_in_clause: (untyped left, untyped right, untyped collector) -> untyped def visit_Arel_Nodes_And: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Or: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Assignment: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Equality: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsNotDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_IsDistinctFrom: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_NotEqual: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_As: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Case: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_When: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_Else: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UnqualifiedColumn: (untyped o, untyped collector) -> untyped def visit_Arel_Attributes_Attribute: (untyped o, untyped collector) -> untyped def literal: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_BindParam: (untyped o, untyped collector) -> untyped def quoted: (untyped o, untyped a) -> untyped def unsupported: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_InfixOperation: (untyped o, untyped collector) -> untyped def visit_Arel_Nodes_UnaryOperation: (untyped o, untyped collector) -> untyped def visit_Array: (untyped o, untyped collector) -> untyped def quote: (untyped value) -> untyped def quote_table_name: (untyped name) -> untyped def quote_column_name: (untyped name) -> untyped def sanitize_as_sql_comment: (untyped value) -> untyped def collect_optimizer_hints: (untyped o, untyped collector) -> untyped def maybe_visit: (untyped thing, untyped collector) -> untyped def inject_join: (untyped list, untyped collector, untyped join_str) -> untyped def unboundable?: (untyped value) -> untyped def has_join_sources?: (untyped o) -> untyped def has_limit_or_offset_or_orders?: (untyped o) -> untyped # The default strategy for an UPDATE with joins is to use a subquery. This doesn't work # on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in # an UPDATE statement, so in the MySQL visitor we redefine this to do that. def prepare_update_statement: (untyped o) -> untyped # FIXME: we should probably have a 2-pass visitor for this def build_subselect: (untyped key, untyped o) -> untyped def infix_value: (untyped o, untyped collector, untyped value) -> untyped def infix_value_with_paren: (untyped o, untyped collector, untyped value, ?bool suppress_parens) -> untyped def aggregate: (untyped name, untyped o, untyped collector) -> untyped def is_distinct_from: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module Visitors class Visitor def initialize: () -> untyped def accept: (untyped object, ?untyped? collector) -> untyped attr_reader dispatch: untyped def self.dispatch_cache: () -> untyped def get_dispatch_cache: () -> untyped def visit: (untyped object, ?untyped? collector) -> untyped end end end module Arel # :nodoc: all module Visitors class WhereSql < Arel::Visitors::ToSql def initialize: (untyped inner_visitor, *untyped args) { () -> untyped } -> untyped def visit_Arel_Nodes_SelectCore: (untyped o, untyped collector) -> untyped end end end module Arel # :nodoc: all module WindowPredications def over: (?untyped? expr) -> Nodes::Over end end module ActiveRecord module Generators class ApplicationRecordGenerator < ::Rails::Generators::Base # FIXME: Change this file to a symlink once RubyGems 2.5.0 is required. def create_application_record: () -> untyped def application_record_file_name: () -> untyped end end end module ActiveRecord module Generators class MigrationGenerator < Base def create_migration_file: () -> untyped attr_reader migration_action: untyped attr_reader join_tables: untyped # Sets the default migration template that is being used for the generation of the migration. # Depending on command line arguments, the migration template and the table name instance # variables are set up. def set_local_assigns!: () -> untyped def set_index_names: () -> untyped def index_name_for: (untyped attribute) -> untyped def attributes_with_index: () -> untyped # A migration file name can only contain underscores (_), lowercase characters, # and numbers 0-9. Any other file name will raise an IllegalMigrationNameError. def validate_file_name!: () -> untyped def normalize_table_name: (untyped _table_name) -> untyped end end end module ActiveRecord module Generators # :nodoc: module Migration extend ActiveSupport::Concern include Rails::Generators::Migration extend ::Rails::Generators::Migration::ClassMethods module ClassMethods # Implement the required interface for Rails::Generators::Migration. def next_migration_number: (untyped dirname) -> untyped end def primary_key_type: () -> untyped def db_migrate_path: () -> untyped def default_migrate_path: () -> untyped def configured_migrate_path: () -> (nil | untyped) end end end module ActiveRecord module Generators class ModelGenerator < Base # creates the migration file for the model. def create_migration_file: () -> (nil | untyped) def create_model_file: () -> untyped def create_module_file: () -> (nil | untyped) def attributes_with_index: () -> untyped # Used by the migration template to determine the parent name of the model def parent_class_name: () -> untyped end end end module ActiveRecord module Generators class Base < Rails::Generators::NamedBase # :nodoc: # :nodoc: include ActiveRecord::Generators::Migration extend ::ActiveRecord::Generators::Migration::ClassMethods # Set the current directory as base for the inherited generators. def self.base_root: () -> untyped end end end