提交 428d47ad 编写于 作者: Y Yves Senn

applies new doc guidelines to Active Record.

The focus of this change is to make the API more accessible.
References to method and classes should be linked to make it easy to
navigate around.

This patch makes exzessiv use of `rdoc-ref:` to provide more readable
docs. This makes it possible to document `ActiveRecord::Base#save` even
though the method is within a separate module
`ActiveRecord::Persistence`. The goal here is to bring the API closer to
the actual code that you would write.

This commit only deals with Active Record. The other gems will be
updated accordingly but in different commits. The pass through Active
Record is not completely finished yet. A follow up commit will change
the spots I haven't yet had the time to update.

/cc @fxn
上级 809fd2b2
module ActiveRecord
# = Active Record Aggregations
module Aggregations # :nodoc:
# See ActiveRecord::Aggregations::ClassMethods for documentation
module Aggregations
extend ActiveSupport::Concern
def initialize_dup(*) # :nodoc:
......@@ -24,7 +24,7 @@ def init_internals # :nodoc:
super
end
# Active Record implements aggregation through a macro-like class method called +composed_of+
# 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
......@@ -120,12 +120,12 @@ def init_internals # :nodoc:
#
# 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
# <tt>Money#exchange_to</tt> 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.
# 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
......@@ -134,17 +134,17 @@ def init_internals # :nodoc:
#
# By default value objects are initialized by calling the <tt>new</tt> constructor of the value
# class passing each of the mapped attributes, in the order specified by the <tt>:mapping</tt>
# option, as arguments. If the value class doesn't support this convention then +composed_of+ allows
# 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).
# 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
# New values can be assigned to the value object using either another +NetAddr::CIDR+ object, a string
# or an array. The <tt>:constructor</tt> and <tt>:converter</tt> options can be used to meet
# these requirements:
#
......@@ -173,7 +173,7 @@ def init_internals # :nodoc:
#
# == Finding records by a value object
#
# Once a +composed_of+ relationship is specified for a model, records can be loaded from the database
# 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 +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
#
......@@ -186,7 +186,7 @@ module ClassMethods
# Options are:
# * <tt>:class_name</tt> - Specifies the class name of the association. Use it only if that name
# can't be inferred from the part id. So <tt>composed_of :address</tt> will by default be linked
# to the Address class, but if the real class name is CompanyAddress, you'll have to specify it
# to the Address class, but if the real class name is +CompanyAddress+, you'll have to specify it
# with this option.
# * <tt>:mapping</tt> - 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
......
......@@ -112,7 +112,7 @@ def select(*fields, &block)
end
# Finds an object in the collection responding to the +id+. Uses the same
# rules as <tt>ActiveRecord::Base.find</tt>. Returns <tt>ActiveRecord::RecordNotFound</tt>
# rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
# error if the object cannot be found.
#
# class Person < ActiveRecord::Base
......@@ -171,27 +171,27 @@ def first(*args)
@association.first(*args)
end
# Same as +first+ except returns only the second record.
# Same as #first except returns only the second record.
def second(*args)
@association.second(*args)
end
# Same as +first+ except returns only the third record.
# Same as #first except returns only the third record.
def third(*args)
@association.third(*args)
end
# Same as +first+ except returns only the fourth record.
# Same as #first except returns only the fourth record.
def fourth(*args)
@association.fourth(*args)
end
# Same as +first+ except returns only the fifth record.
# Same as #first except returns only the fifth record.
def fifth(*args)
@association.fifth(*args)
end
# Same as +first+ except returns only the forty second record.
# Same as #first except returns only the forty second record.
# Also known as accessing "the reddit".
def forty_two(*args)
@association.forty_two(*args)
......@@ -315,7 +315,7 @@ def create(attributes = {}, &block)
@association.create(attributes, &block)
end
# Like +create+, except that if the record is invalid, raises an exception.
# Like #create, except that if the record is invalid, raises an exception.
#
# class Person
# has_many :pets
......@@ -332,8 +332,8 @@ def create!(attributes = {}, &block)
end
# Add 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+
# to the association's primary key. Since #<< flattens its argument list and
# inserts each record, +push+ and #concat behave identically. Returns +self+
# so method calls may be chained.
#
# class Person < ActiveRecord::Base
......
......@@ -5,7 +5,7 @@ module AttributeAssignment
extend ActiveSupport::Concern
include ActiveModel::AttributeAssignment
# Alias for `assign_attributes`. See +ActiveModel::AttributeAssignment+.
# Alias for ActiveModel::AttributeAssignment#assign_attributes. See ActiveModel::AttributeAssignment.
def attributes=(attributes)
assign_attributes(attributes)
end
......
......@@ -96,7 +96,7 @@ def undefine_attribute_methods # :nodoc:
end
end
# Raises an <tt>ActiveRecord::DangerousAttributeError</tt> exception when an
# Raises an ActiveRecord::DangerousAttributeError exception when an
# \Active \Record method is defined in the model, otherwise +false+.
#
# class Person < ActiveRecord::Base
......@@ -346,7 +346,7 @@ def attribute_present?(attribute)
#
# Note: +:id+ is always present.
#
# Alias for the <tt>read_attribute</tt> method.
# Alias for the #read_attribute method.
#
# class Person < ActiveRecord::Base
# belongs_to :organization
......@@ -364,7 +364,7 @@ def [](attr_name)
end
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
# (Alias for the protected <tt>write_attribute</tt> method).
# (Alias for the protected #write_attribute method).
#
# class Person < ActiveRecord::Base
# end
......
......@@ -2,7 +2,7 @@ module ActiveRecord
module AttributeMethods
# = Active Record Attribute Methods Before Type Cast
#
# <tt>ActiveRecord::AttributeMethods::BeforeTypeCast</tt> provides a way to
# ActiveRecord::AttributeMethods::BeforeTypeCast provides a way to
# read the value of the attributes before typecasting and deserialization.
#
# class Task < ActiveRecord::Base
......
......@@ -5,7 +5,7 @@ module AttributeMethods
module PrimaryKey
extend ActiveSupport::Concern
# Returns this record's primary key value wrapped in an Array if one is
# Returns this record's primary key value wrapped in an array if one is
# available.
def to_key
sync_with_transaction_state
......@@ -108,7 +108,7 @@ def get_primary_key(base_name) #:nodoc:
# self.primary_key = 'sysid'
# end
#
# You can also define the +primary_key+ method yourself:
# You can also define the #primary_key method yourself:
#
# class Project < ActiveRecord::Base
# def self.primary_key
......
......@@ -9,7 +9,7 @@ module ClassMethods
# 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 <tt>SerializationTypeMismatch</tt> will be raised.
# Otherwise SerializationTypeMismatch will be raised.
#
# Empty objects as <tt>{}</tt>, in the case of +Hash+, or <tt>[]</tt>, in the case of
# +Array+, will always be persisted as null.
......@@ -17,7 +17,7 @@ module ClassMethods
# 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
# objects transparently. There is no need to use #serialize in this
# case.
#
# For more complex cases, such as conversion to or from your application
......
......@@ -15,7 +15,7 @@ module ClassMethods
# 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::QueryMethods#where. This will let you use
# {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.
#
......@@ -87,7 +87,7 @@ module ClassMethods
# 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.
# \Attributes do not need to be backed by a database column.
#
# class MyModel < ActiveRecord::Base
# attribute :my_string, :string
......@@ -144,9 +144,9 @@ module ClassMethods
# to be referenced by a symbol, see ActiveRecord::Type.register. You can
# also pass a type object directly, in place of a symbol.
#
# ==== Querying
# ==== \Querying
#
# When ActiveRecord::QueryMethods#where is called, it will
# 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:
#
......
module ActiveRecord
# = Active Record Autosave Association
#
# +AutosaveAssociation+ is a module that takes care of automatically saving
# 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 <tt>marked_for_destruction?</tt>).
# (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
......@@ -125,7 +125,6 @@ module ActiveRecord
# Now it _is_ removed from the database:
#
# Comment.find_by(id: id).nil? # => true
module AutosaveAssociation
extend ActiveSupport::Concern
......@@ -353,7 +352,7 @@ def before_save_collection_association
# <tt>:autosave</tt> is enabled on the association.
#
# In addition, it destroys all children that were marked for destruction
# with mark_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.
......@@ -396,7 +395,7 @@ def save_collection_association(reflection)
# on the association.
#
# In addition, it will destroy the association if it was marked for
# destruction with mark_for_destruction.
# 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.
......
......@@ -170,7 +170,7 @@ module ActiveRecord #:nodoc:
# <tt>Person.find_by_user_name(user_name)</tt>.
#
# It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
# <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records,
# ActiveRecord::RecordNotFound error if they do not return any records,
# like <tt>Person.find_by_last_name!</tt>.
#
# It's also possible to use multiple attributes in the same find by separating them with "_and_".
......@@ -185,7 +185,8 @@ module ActiveRecord #:nodoc:
# == 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+.
# 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.
#
......@@ -225,39 +226,47 @@ module ActiveRecord #:nodoc:
#
# == Connection to multiple databases in different models
#
# Connections are usually created through ActiveRecord::Base.establish_connection and retrieved
# 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 <tt>Course.establish_connection</tt>
# 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 retrieve_connection method
# 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 <tt>establish_connection</tt> didn't include an
# <tt>:adapter</tt> key.
# * AdapterNotFound - The <tt>:adapter</tt> key used in <tt>establish_connection</tt> specified a
# non-existent adapter
# * AdapterNotSpecified - The configuration hash used in
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
# didn't include an <tt>:adapter</tt> key.
# * AdapterNotFound - The <tt>:adapter</tt> 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
# <tt>attributes=</tt> method.
# {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 <tt>establish_connection</tt>
# before querying.
# * 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
# <tt>attributes=</tt> method. The +errors+ property of this exception contains an array of
# {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 <tt>save!</tt> and <tt>create!</tt> when the record is invalid.
# * RecordNotFound - No record responded to the +find+ method. Either the row with the given ID doesn't exist
# or the row didn't meet the additional restrictions. Some +find+ calls do not raise this exception to signal
# * 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.
......
module ActiveRecord
# = Active Record Callbacks
# = Active Record \Callbacks
#
# Callbacks are hooks into the life cycle of an Active Record object that allow you to trigger logic
# \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 +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 <tt>Base#save</tt> call for a new record:
# 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:
#
# * (-) <tt>save</tt>
# * (-) <tt>valid</tt>
......@@ -20,7 +20,7 @@ module ActiveRecord
# * (7) <tt>after_commit</tt>
#
# Also, an <tt>after_rollback</tt> callback can be configured to be triggered whenever a rollback is issued.
# Check out <tt>ActiveRecord::Transactions</tt> for more details about <tt>after_commit</tt> and
# Check out ActiveRecord::Transactions for more details about <tt>after_commit</tt> and
# <tt>after_rollback</tt>.
#
# Additionally, an <tt>after_touch</tt> callback is triggered whenever an
......@@ -31,7 +31,7 @@ module ActiveRecord
# 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 <tt>Base#save</tt> for an existing record is similar,
# Active Record life cycle. The sequence for calling {ActiveRecord::Base#save}[rdoc-ref:Persistence#save] for an existing record is similar,
# except that each <tt>_create</tt> callback is replaced by the corresponding <tt>_update</tt> callback.
#
# Examples:
......@@ -193,8 +193,9 @@ module ActiveRecord
# == <tt>before_validation*</tt> returning statements
#
# If the +before_validation+ callback throws +:abort+, the process will be
# aborted and <tt>Base#save</tt> will return +false+. If Base#save! is called it will raise a
# <tt>ActiveRecord::RecordInvalid</tt> exception. Nothing will be appended to the errors object.
# 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 a ActiveRecord::RecordInvalid exception.
# Nothing will be appended to the errors object.
#
# == Canceling callbacks
#
......@@ -223,7 +224,8 @@ module ActiveRecord
# end
#
# In this case, the problem is that when the +before_destroy+ callback is executed, the children are not available
# because the +destroy+ callback gets executed first. You can use the +prepend+ option on the +before_destroy+ callback to avoid this.
# 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
......@@ -238,21 +240,21 @@ module ActiveRecord
#
# This way, the +before_destroy+ gets executed before the <tt>dependent: destroy</tt> is called, and the data is still available.
#
# == Transactions
# == \Transactions
#
# The entire callback chain of a +save+, <tt>save!</tt>, or +destroy+ call runs
# within a transaction. That includes <tt>after_*</tt> hooks. If everything
# goes fine a COMMIT is executed once the chain has been completed.
# 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 <tt>after_*</tt> hooks.
# If everything goes fine a COMMIT is executed once the chain has been completed.
#
# If a <tt>before_*</tt> callback cancels the action a ROLLBACK is issued. You
# can also trigger a ROLLBACK raising an exception in any of the callbacks,
# including <tt>after_*</tt> hooks. Note, however, that in that case the client
# needs to be aware of it because an ordinary +save+ will raise such exception
# 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 <tt>_*_callbacks</tt> method on an object. ActiveModel Callbacks support
# The callback chain is accessible via the <tt>_*_callbacks</tt> method on an object. Active Model \Callbacks support
# <tt>:before</tt>, <tt>:after</tt> and <tt>:around</tt> as values for the <tt>kind</tt> property. The <tt>kind</tt> property
# defines what part of the chain the callback runs in.
#
......
......@@ -10,8 +10,9 @@ class ConnectionTimeoutError < ConnectionNotEstablished
end
# Raised when a pool was unable to get ahold of all its connections
# to perform a "group" action such as +ConnectionPool#disconnect!+
# or +ConnectionPool#clear_reloadable_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
......@@ -37,17 +38,18 @@ module ConnectionAdapters
# Connections can be obtained and used from a connection pool in several
# ways:
#
# 1. Simply use ActiveRecord::Base.connection as with Active Record 2.1 and
# 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!. This will be the
# default behavior for Active Record when used in conjunction with
# {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. You are responsible for
# {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).
# 3. Use ActiveRecord::Base.connection_pool.with_connection(&block), which
# {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.
#
......@@ -140,7 +142,7 @@ def clear
# become available.
#
# Raises:
# - ConnectionTimeoutError if +timeout+ is given and no element
# - ActiveRecord::ConnectionTimeoutError if +timeout+ is given and no element
# becomes available within +timeout+ seconds,
def poll(timeout = nil)
synchronize { internal_poll(timeout) }
......@@ -406,7 +408,7 @@ def connected?
# Disconnects all connections in the pool, and clears the pool.
#
# Raises:
# - +ExclusiveConnectionTimeoutError+ if unable to gain ownership of all
# - ActiveRecord::ExclusiveConnectionTimeoutError if unable to gain ownership of all
# connections in the pool within a timeout interval (default duration is
# <tt>spec.config[:checkout_timeout] * 2</tt> seconds).
def disconnect(raise_on_acquisition_timeout = true)
......@@ -436,7 +438,7 @@ def disconnect!
# require reloading.
#
# Raises:
# - +ExclusiveConnectionTimeoutError+ if unable to gain ownership of all
# - ActiveRecord::ExclusiveConnectionTimeoutError if unable to gain ownership of all
# connections in the pool within a timeout interval (default duration is
# <tt>spec.config[:checkout_timeout] * 2</tt> seconds).
def clear_reloadable_connections(raise_on_acquisition_timeout = true)
......@@ -494,7 +496,7 @@ def clear_reloadable_connections!
# Returns: an AbstractAdapter object.
#
# Raises:
# - ConnectionTimeoutError: no connection can be obtained from the pool.
# - ActiveRecord::ConnectionTimeoutError no connection can be obtained from the pool.
def checkout(checkout_timeout = @checkout_timeout)
checkout_and_verify(acquire_connection(checkout_timeout))
end
......@@ -503,7 +505,7 @@ def checkout(checkout_timeout = @checkout_timeout)
# no longer need this connection.
#
# +conn+: an AbstractAdapter object, which was obtained by earlier by
# calling +checkout+ on this pool.
# calling #checkout on this pool.
def checkin(conn)
synchronize do
remove_connection_from_thread_cache conn
......@@ -516,7 +518,7 @@ def checkin(conn)
end
end
# Remove a connection from the connection pool. The connection will
# 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(conn)
needs_new_connection = false
......@@ -547,7 +549,7 @@ def remove(conn)
bulk_make_new_connections(1) if needs_new_connection
end
# Recover lost connections for the pool. A lost connection can occur if
# 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
......@@ -688,7 +690,7 @@ def with_new_connections_blocked
# queue for a connection to become available.
#
# Raises:
# - ConnectionTimeoutError if a connection could not be acquired
# - ActiveRecord::ConnectionTimeoutError if a connection could not be acquired
#
#--
# Implementation detail: the connection returned by +acquire_connection+
......@@ -857,6 +859,8 @@ def clear_active_connections!
end
# Clears the cache which maps classes.
#
# See ConnectionPool#clear_reloadable_connections! for details.
def clear_reloadable_connections!
connection_pool_list.each(&:clear_reloadable_connections!)
end
......
......@@ -19,8 +19,8 @@ def table_name_length
# Returns the maximum allowed length for an index name. This
# limit is enforced by \Rails and is less than or equal to
# <tt>index_name_length</tt>. The gap between
# <tt>index_name_length</tt> is to allow internal \Rails
# #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
index_name_length
......
......@@ -192,7 +192,7 @@ def supports_statement_cache?
# * http://www.postgresql.org/docs/current/static/transaction-iso.html
# * https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
#
# An <tt>ActiveRecord::TransactionIsolationError</tt> will be raised if:
# An ActiveRecord::TransactionIsolationError will be raised if:
#
# * The adapter does not support setting the isolation level
# * You are joining an existing open transaction
......
......@@ -43,9 +43,9 @@ def type_cast(value, column = nil)
# If you are having to call this function, you are likely doing something
# wrong. The column does not have sufficient type information if the user
# provided a custom type on the class level either explicitly (via
# `attribute`) or implicitly (via `serialize`,
# `time_zone_aware_attributes`). In almost all cases, the sql type should
# only be used to change quoting behavior, when the primitive to
# Attributes::ClassMethods#attribute) or implicitly (via
# AttributeMethods::Serialization::ClassMethods#serialize, +time_zone_aware_attributes+).
# In almost all cases, the sql type should only be used to change quoting behavior, when the primitive to
# represent the type doesn't sufficiently reflect the differences
# (varchar vs binary) for example. The type used to get this primitive
# should have been provided before reaching the connection adapter.
......@@ -58,7 +58,7 @@ def type_cast_from_column(column, value) # :nodoc:
end
end
# See docs for +type_cast_from_column+
# See docs for #type_cast_from_column
def lookup_cast_type_from_column(column) # :nodoc:
lookup_cast_type(column.sql_type)
end
......
......@@ -187,7 +187,7 @@ def #{column_type}(*args, **options)
# 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+
# Inside migration files, the +t+ object in {create_table}[rdoc-ref:SchemaStatements#create_table]
# is actually of this type:
#
# class SomeMigration < ActiveRecord::Migration
......@@ -203,7 +203,7 @@ def #{column_type}(*args, **options)
# end
#
# The table definitions
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
# The Columns are stored as a ColumnDefinition in the #columns attribute.
class TableDefinition
include ColumnMethods
......@@ -321,7 +321,7 @@ def [](name)
#
# == Short-hand examples
#
# Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
# 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.
#
......@@ -353,7 +353,8 @@ def [](name)
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
# will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
# 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
......@@ -404,7 +405,7 @@ def foreign_key(table_name, options = {}) # :nodoc:
end
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
# <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
# <tt>:updated_at</tt> to the table. See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
#
# t.timestamps null: false
def timestamps(*args)
......@@ -421,7 +422,7 @@ def timestamps(*args)
# t.references(:user)
# t.belongs_to(:supplier, foreign_key: true)
#
# See SchemaStatements#add_reference for details of the options you can use.
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
def references(*args, **options)
args.each do |col|
ReferenceDefinition.new(col, **options).add_to(self)
......@@ -493,7 +494,7 @@ def add_column(name, type, options)
end
# Represents an SQL table in an abstract way for updating a table.
# Also see TableDefinition and SchemaStatements#create_table
# Also see TableDefinition and {connection.create_table}[rdoc-ref:SchemaStatements#create_table]
#
# Available transformations are:
#
......@@ -550,7 +551,7 @@ def column(column_name, type, options = {})
#
# t.string(:name) unless t.column_exists?(:name, :string)
#
# See SchemaStatements#column_exists?
# See {connection.column_exists?}[rdoc-ref:SchemaStatements#column_exists?]
def column_exists?(column_name, type = nil, options = {})
@base.column_exists?(name, column_name, type, options)
end
......@@ -562,7 +563,7 @@ def column_exists?(column_name, type = nil, options = {})
# t.index([:branch_id, :party_id], unique: true)
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
#
# See SchemaStatements#add_index for details of the options you can use.
# See {connection.add_index}[rdoc-ref:SchemaStatements#add_index] for details of the options you can use.
def index(column_name, options = {})
@base.add_index(name, column_name, options)
end
......@@ -573,7 +574,7 @@ def index(column_name, options = {})
# t.index(:branch_id)
# end
#
# See SchemaStatements#index_exists?
# See {connection.index_exists?}[rdoc-ref:SchemaStatements#index_exists?]
def index_exists?(column_name, options = {})
@base.index_exists?(name, column_name, options)
end
......@@ -582,7 +583,7 @@ def index_exists?(column_name, options = {})
#
# t.rename_index(:user_id, :account_id)
#
# See SchemaStatements#rename_index
# See {connection.rename_index}[rdoc-ref:SchemaStatements#rename_index]
def rename_index(index_name, new_index_name)
@base.rename_index(name, index_name, new_index_name)
end
......@@ -591,7 +592,7 @@ def rename_index(index_name, new_index_name)
#
# t.timestamps(null: false)
#
# See SchemaStatements#add_timestamps
# See {connection.add_timestamps}[rdoc-ref:SchemaStatements#add_timestamps]
def timestamps(options = {})
@base.add_timestamps(name, options)
end
......@@ -612,7 +613,7 @@ def change(column_name, type, options = {})
# t.change_default(:authorized, 1)
# t.change_default(:status, from: nil, to: "draft")
#
# See SchemaStatements#change_column_default
# See {connection.change_column_default}[rdoc-ref:SchemaStatements#change_column_default]
def change_default(column_name, default_or_changes)
@base.change_column_default(name, column_name, default_or_changes)
end
......@@ -622,7 +623,7 @@ def change_default(column_name, default_or_changes)
# t.remove(:qualification)
# t.remove(:qualification, :experience)
#
# See SchemaStatements#remove_columns
# See {connection.remove_columns}[rdoc-ref:SchemaStatements#remove_columns]
def remove(*column_names)
@base.remove_columns(name, *column_names)
end
......@@ -633,7 +634,7 @@ def remove(*column_names)
# t.remove_index(column: [:branch_id, :party_id])
# t.remove_index(name: :by_branch_party)
#
# See SchemaStatements#remove_index
# See {connection.remove_index}[rdoc-ref:SchemaStatements#remove_index]
def remove_index(options = {})
@base.remove_index(name, options)
end
......@@ -642,7 +643,7 @@ def remove_index(options = {})
#
# t.remove_timestamps
#
# See SchemaStatements#remove_timestamps
# See {connection.remove_timestamps}[rdoc-ref:SchemaStatements#remove_timestamps]
def remove_timestamps(options = {})
@base.remove_timestamps(name, options)
end
......@@ -651,7 +652,7 @@ def remove_timestamps(options = {})
#
# t.rename(:description, :name)
#
# See SchemaStatements#rename_column
# See {connection.rename_column}[rdoc-ref:SchemaStatements#rename_column]
def rename(column_name, new_column_name)
@base.rename_column(name, column_name, new_column_name)
end
......@@ -661,7 +662,7 @@ def rename(column_name, new_column_name)
# t.references(:user)
# t.belongs_to(:supplier, foreign_key: true)
#
# See SchemaStatements#add_reference for details of the options you can use.
# See {connection.add_reference}[rdoc-ref:SchemaStatements#add_reference] for details of the options you can use.
def references(*args)
options = args.extract_options!
args.each do |ref_name|
......@@ -675,7 +676,7 @@ def references(*args)
# t.remove_references(:user)
# t.remove_belongs_to(:supplier, polymorphic: true)
#
# See SchemaStatements#remove_reference
# See {connection.remove_reference}[rdoc-ref:SchemaStatements#remove_reference]
def remove_references(*args)
options = args.extract_options!
args.each do |ref_name|
......@@ -688,7 +689,7 @@ def remove_references(*args)
#
# t.foreign_key(:authors)
#
# See SchemaStatements#add_foreign_key
# See {connection.add_foreign_key}[rdoc-ref:SchemaStatements#add_foreign_key]
def foreign_key(*args) # :nodoc:
@base.add_foreign_key(name, *args)
end
......@@ -697,7 +698,7 @@ def foreign_key(*args) # :nodoc:
#
# t.foreign_key(:authors) unless t.foreign_key_exists?(:authors)
#
# See SchemaStatements#foreign_key_exists?
# See {connection.foreign_key_exists?}[rdoc-ref:SchemaStatements#foreign_key_exists?]
def foreign_key_exists?(*args) # :nodoc:
@base.foreign_key_exists?(name, *args)
end
......
......@@ -129,7 +129,7 @@ def primary_key(table_name)
# 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
# There are two ways to work with #create_table. You can use the block
# form or the regular form, like this:
#
# === Block form
......@@ -161,7 +161,7 @@ def primary_key(table_name)
# The +options+ hash can include the following keys:
# [<tt>:id</tt>]
# Whether to automatically add a primary key column. Defaults to true.
# Join tables for +has_and_belongs_to_many+ should set it to false.
# 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.
# [<tt>:primary_key</tt>]
......@@ -169,7 +169,8 @@ def primary_key(table_name)
# Defaults to +id+. If <tt>:id</tt> is false this option is ignored.
#
# Note that Active Record models will automatically detect their
# primary key. This can be avoided by using +self.primary_key=+ on the model
# 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.
#
# [<tt>:options</tt>]
......@@ -296,7 +297,7 @@ def create_table(table_name, options = {})
# 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
# 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|
......@@ -331,11 +332,11 @@ def create_join_table(table_1, table_2, options = {})
end
# Drops the join table specified by the given arguments.
# See +create_join_table+ for details.
# 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.
# In that case, the block will be used by #create_join_table.
def drop_join_table(table_1, table_2, options = {})
join_table_name = find_join_table_name(table_1, table_2, options)
drop_table(join_table_name)
......@@ -440,7 +441,7 @@ def rename_table(table_name, new_name)
#
# 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.
# In that case, +options+ and the block will be used by #create_table.
def drop_table(table_name, options = {})
execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
end
......@@ -694,7 +695,7 @@ def index_name_exists?(table_name, index_name, default)
# Adds a reference. The reference column is an integer by default,
# the <tt>:type</tt> option can be used to specify a different type.
# Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
# <tt>add_reference</tt> and <tt>add_belongs_to</tt> are acceptable.
# #add_reference and #add_belongs_to are acceptable.
#
# The +options+ hash can include the following keys:
# [<tt>:type</tt>]
......@@ -734,7 +735,7 @@ def add_reference(table_name, *args)
alias :add_belongs_to :add_reference
# Removes the reference(s). Also removes a +type+ column if one exists.
# <tt>remove_reference</tt> and <tt>remove_belongs_to</tt> are acceptable.
# #remove_reference and #remove_belongs_to are acceptable.
#
# ====== Remove the reference
#
......@@ -760,7 +761,7 @@ def remove_reference(table_name, ref_name, options = {})
alias :remove_belongs_to :remove_reference
# Returns an array of foreign keys for the given table.
# The foreign keys are represented as +ForeignKeyDefinition+ objects.
# The foreign keys are represented as ForeignKeyDefinition objects.
def foreign_keys(table_name)
raise NotImplementedError, "foreign_keys is not implemented"
end
......
......@@ -51,15 +51,15 @@ module ConnectionAdapters # :nodoc:
# 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.
# a connection, escaping values, building the right SQL fragments for +:offset+
# and +:limit+ options, etc.
#
# All the concrete database adapters follow the interface laid down in this class.
# ActiveRecord::Base.connection returns an AbstractAdapter object, which
# {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 SchemaStatement are very useful.
# notably, the instance methods provided by SchemaStatements are very useful.
class AbstractAdapter
ADAPTER_NAME = 'Abstract'.freeze
include Quoting, DatabaseStatements, SchemaStatements
......@@ -348,7 +348,7 @@ def requires_reloading?
end
# Checks whether the connection to the database is still active (i.e. not stale).
# This is done under the hood by calling <tt>active?</tt>. If the connection
# 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!(*ignored)
reconnect! unless active?
......
......@@ -125,7 +125,7 @@ def schema_creation # :nodoc:
PostgreSQL::SchemaCreation.new self
end
# Returns +true+, since this connection adapter supports prepared statement
# Returns true, since this connection adapter supports prepared statement
# caching.
def supports_statement_cache?
true
......
......@@ -35,14 +35,14 @@ module ConnectionHandling
# "postgres://myuser:mypass@localhost/somedatabase"
# )
#
# In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
# automatically loads the contents of config/database.yml into it),
# 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+
# The exceptions AdapterNotSpecified, AdapterNotFound and +ArgumentError+
# may be returned on an error.
def establish_connection(spec = nil)
spec ||= DEFAULT_ENV.call.to_sym
......
......@@ -310,7 +310,7 @@ def initialize(attributes = nil)
# Initialize an empty model object from +coder+. +coder+ should be
# the result of previously encoding an Active Record model, using
# `encode_with`
# #encode_with.
#
# class Post < ActiveRecord::Base
# end
......@@ -379,7 +379,7 @@ def initialize_dup(other) # :nodoc:
# 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+
# guaranteed to match the structure of +coder+ passed to the #init_with
# method.
#
# Example:
......@@ -477,7 +477,7 @@ def inspect
"#<#{self.class} #{inspection}>"
end
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
# Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
# when pp is required.
def pretty_print(pp)
return super if custom_inspect_method_defined?
......
......@@ -45,14 +45,14 @@ def reset_counters(id, *counters)
end
# A generic "counter updater" implementation, intended primarily to be
# used by increment_counter and decrement_counter, but which may also
# 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.
# * +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.
#
......@@ -86,14 +86,14 @@ def update_counters(id, counters)
# 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
# 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.
# * +id+ - The id of the object that should be incremented or an array of ids.
#
# ==== Examples
#
......@@ -105,13 +105,13 @@ def increment_counter(counter_name, id)
# Decrement a numeric field by one, via a direct SQL update.
#
# This works the same as increment_counter but reduces the column value by
# 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.
# * +id+ - The id of the object that should be decremented or an array of ids.
#
# ==== Examples
#
......
......@@ -46,13 +46,13 @@ module ActiveRecord
# Good practice is to let the first declared status be the default.
#
# Finally, it's also possible to explicitly map the relation between attribute and
# database integer with a +Hash+:
# database integer with a hash:
#
# class Conversation < ActiveRecord::Base
# enum status: { active: 0, archived: 1 }
# end
#
# Note that when an +Array+ is used, the implicit mapping from the values to database
# Note that when an array is used, the implicit mapping from the values to database
# integers is derived from the order the values appear in the array. In the example,
# <tt>:active</tt> is mapped to +0+ as it's the first element, and <tt>:archived</tt>
# is mapped to +1+. In general, the +i+-th element is mapped to <tt>i-1</tt> in the
......@@ -60,7 +60,7 @@ module ActiveRecord
#
# Therefore, once a value is added to the enum array, its position in the array must
# be maintained, and new values should only be added to the end of the array. To
# remove unused values, the explicit +Hash+ syntax should be used.
# remove unused values, the explicit hash syntax should be used.
#
# In rare circumstances you might need to access the mapping directly.
# The mappings are exposed through a class method with the pluralized attribute
......
......@@ -7,8 +7,10 @@ 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 +inheritance_column+ points to).
class SubclassNotFound < ActiveRecordError #:nodoc:
# (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.
......@@ -40,12 +42,13 @@ class AdapterNotSpecified < ActiveRecordError
class AdapterNotFound < ActiveRecordError
end
# Raised when connection to the database could not been established (for
# example when +connection=+ is given a nil object).
# 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 Active Record cannot find record by given id or set of ids.
# Raised when Active Record cannot find a record by given id or set of ids.
class RecordNotFound < ActiveRecordError
attr_reader :model, :primary_key, :id
......@@ -58,8 +61,9 @@ def initialize(message = nil, model = nil, primary_key = nil, id = nil)
end
end
# Raised by ActiveRecord::Base.save! and ActiveRecord::Base.create! methods when record cannot be
# saved because record is invalid.
# 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 can not be saved.
class RecordNotSaved < ActiveRecordError
attr_reader :record
......@@ -69,7 +73,9 @@ def initialize(message = nil, record = nil)
end
end
# Raised by ActiveRecord::Base.destroy! when a call to destroy would return false.
# 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!
......@@ -99,7 +105,7 @@ def initialize(message = nil, original_exception = nil)
end
# Defunct wrapper class kept for compatibility.
# +StatementInvalid+ wraps the original exception now.
# StatementInvalid wraps the original exception now.
class WrappedDatabaseException < StatementInvalid
end
......@@ -112,8 +118,8 @@ class InvalidForeignKey < WrappedDatabaseException
end
# Raised when number of bind variables in statement given to +:condition+ key
# (for example, when using +find+ method) does not match number of expected
# values supplied.
# (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:
#
......@@ -147,7 +153,9 @@ def initialize(record = nil, attempted_action = nil)
end
# Raised when association is being configured improperly or user tries to use
# offset and limit together with +has_many+ or +has_and_belongs_to_many+
# 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
......@@ -156,9 +164,10 @@ class ConfigurationError < ActiveRecordError
class ReadOnlyRecord < ActiveRecordError
end
# ActiveRecord::Transactions::ClassMethods.transaction uses this exception
# to distinguish a deliberate rollback from other exceptional situations.
# Normally, raising an exception will cause the +transaction+ method to rollback
# {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.
......@@ -195,8 +204,8 @@ class DangerousAttributeError < ActiveRecordError
UnknownAttributeError = ActiveModel::UnknownAttributeError
# Raised when an error occurred while doing a mass assignment to an attribute through the
# +attributes=+ method. The exception has an +attribute+ property that is the name of the
# offending attribute.
# {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, :attribute
......@@ -207,7 +216,8 @@ def initialize(message = nil, exception = nil, attribute = nil)
end
end
# Raised when there are multiple errors while doing a mass assignment through the +attributes+
# 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
......
......@@ -7,7 +7,7 @@ module ActiveRecord
#
# returns the collected queries local to the current thread.
#
# See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
# See the documentation of ActiveSupport::PerThreadRegistry
# for further details.
class ExplainRegistry # :nodoc:
extend ActiveSupport::PerThreadRegistry
......
......@@ -89,7 +89,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
# end
#
# In order to use these methods to access fixtured data within your testcases, you must specify one of the
# following in your <tt>ActiveSupport::TestCase</tt>-derived class:
# following in your ActiveSupport::TestCase-derived class:
#
# - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
# self.use_instantiated_fixtures = true
......@@ -124,7 +124,7 @@ class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
#
# 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 <tt>ActiveRecord::FixtureSet.context_class</tt>.
# that is included in ActiveRecord::FixtureSet.context_class.
#
# - define a helper method in `test_helper.rb`
# module FixtureFileHelpers
......
module ActiveRecord
# = Active Record Persistence
# = Active Record \Persistence
module Persistence
extend ActiveSupport::Concern
......@@ -106,7 +106,7 @@ def persisted?
# the existing record gets updated.
#
# By default, save always run validations. If any of them fail the action
# is cancelled and +save+ returns +false+. However, if you supply
# is cancelled and #save returns +false+. However, if you supply
# validate: false, validations are bypassed altogether. See
# ActiveRecord::Validations for more information.
#
......@@ -132,7 +132,7 @@ def save(*args)
# If the model is new, a record gets created in the database, otherwise
# the existing record gets updated.
#
# With <tt>save!</tt> validations always run. If any of them fail
# With #save! validations always run. If any of them fail
# ActiveRecord::RecordInvalid gets raised. See ActiveRecord::Validations
# for more information.
#
......@@ -158,7 +158,7 @@ def save!(*args)
# 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 <tt>readonly?</tt>.
# 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 <tt>:dependent</tt> association
......@@ -207,7 +207,7 @@ def destroy!
# 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.
# If you want to change the sti column as well, use #becomes! instead.
def becomes(klass)
became = klass.new
became.instance_variable_set("@attributes", @attributes)
......@@ -219,7 +219,7 @@ def becomes(klass)
became
end
# Wrapper around +becomes+ that also changes the instance's sti column value.
# 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.
#
......@@ -239,14 +239,14 @@ def becomes!(klass)
# This is especially useful for boolean flags on existing records. Also note that
#
# * Validation is skipped.
# * Callbacks are invoked.
# * \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
# This method raises an ActiveRecord::ActiveRecordError if the
# attribute is marked as readonly.
#
# See also +update_column+.
# See also #update_column.
def update_attribute(name, value)
name = name.to_s
verify_readonly_attribute(name)
......@@ -268,7 +268,7 @@ def update(attributes)
alias update_attributes update
# Updates its receiver just like +update+ but calls <tt>save!</tt> instead
# Updates its receiver just like #update but calls #save! instead
# of +save+, so an exception is raised if the record is invalid.
def update!(attributes)
# The following transaction covers any possible database side-effects of the
......@@ -295,11 +295,11 @@ def update_column(name, value)
# the database, but take into account that in consequence the regular update
# procedures are totally bypassed. In particular:
#
# * Validations are skipped.
# * Callbacks are skipped.
# * \Validations are skipped.
# * \Callbacks are skipped.
# * +updated_at+/+updated_on+ are not updated.
#
# This method raises an +ActiveRecord::ActiveRecordError+ when called on new
# 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(attributes)
raise ActiveRecordError, "cannot update a new record" if new_record?
......@@ -327,7 +327,7 @@ def increment(attribute, by = 1)
self
end
# Wrapper around +increment+ that saves the record. This method differs from
# Wrapper around #increment that saves the record. This method differs from
# its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
......@@ -346,7 +346,7 @@ def decrement(attribute, by = 1)
increment(attribute, -by)
end
# Wrapper around +decrement+ that saves the record. This method differs from
# Wrapper around #decrement that saves the record. This method differs from
# its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
......@@ -363,7 +363,7 @@ def toggle(attribute)
self
end
# Wrapper around +toggle+ that saves the record. This method differs from
# Wrapper around #toggle that saves the record. This method differs from
# its non-bang version in that it passes through the attribute setter.
# Saving is not subjected to validation checks. Returns +true+ if the
# record could be saved.
......@@ -386,7 +386,7 @@ def toggle!(attribute)
# 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 <tt>ActiveRecord::RecordNotFound</tt>
# 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.
#
......@@ -448,8 +448,8 @@ def reload(options = nil)
# product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
# product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
#
# If used along with +belongs_to+ then +touch+ will invoke +touch+ method on
# associated object.
# 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
......
require "arel/collectors/bind"
module ActiveRecord
# = Active Record Relation
# = Active Record \Relation
class Relation
MULTI_VALUE_METHODS = [:includes, :eager_load, :preload, :select, :group,
:order, :joins, :references,
......@@ -108,7 +108,7 @@ def substitute_values(values) # :nodoc:
# Initializes new record from relation while maintaining the current
# scope.
#
# Expects arguments in the same format as +Base.new+.
# Expects arguments in the same format as {ActiveRecord::Base.new}[rdoc-ref:Core.new].
#
# users = User.where(name: 'DHH')
# user = users.new # => #<User id: nil, name: "DHH", created_at: nil, updated_at: nil>
......@@ -126,28 +126,32 @@ def new(*args, &block)
# Tries to create a new record with the same scoped attributes
# defined in the relation. Returns the initialized object if validation fails.
#
# Expects arguments in the same format as +Base.create+.
# Expects arguments in the same format as
# {ActiveRecord::Base.create}[rdoc-ref:Persistence::ClassMethods#create].
#
# ==== Examples
#
# users = User.where(name: 'Oscar')
# users.create # #<User id: 3, name: "oscar", ...>
# users.create # => #<User id: 3, name: "oscar", ...>
#
# users.create(name: 'fxn')
# users.create # #<User id: 4, name: "fxn", ...>
# users.create # => #<User id: 4, name: "fxn", ...>
#
# users.create { |user| user.name = 'tenderlove' }
# # #<User id: 5, name: "tenderlove", ...>
# # => #<User id: 5, name: "tenderlove", ...>
#
# users.create(name: nil) # validation on name
# # #<User id: nil, name: nil, ...>
# # => #<User id: nil, name: nil, ...>
def create(*args, &block)
scoping { @klass.create(*args, &block) }
end
# Similar to #create, but calls +create!+ on the base class. Raises
# an exception if a validation error occurs.
# 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 <tt>Base.create!</tt>.
# Expects arguments in the same format as
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!].
def create!(*args, &block)
scoping { @klass.create!(*args, &block) }
end
......@@ -181,7 +185,7 @@ def first_or_initialize(attributes = nil, &block) # :nodoc:
# User.create_with(last_name: 'Johansson').find_or_create_by(first_name: 'Scarlett')
# # => #<User id: 2, first_name: "Scarlett", last_name: "Johansson">
#
# This method accepts a block, which is passed down to +create+. The last example
# 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
......@@ -193,7 +197,7 @@ def first_or_initialize(attributes = nil, &block) # :nodoc:
#
# 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.
# #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
......@@ -216,13 +220,15 @@ def find_or_create_by(attributes, &block)
find_by(attributes) || create(attributes, &block)
end
# Like <tt>find_or_create_by</tt>, but calls <tt>create!</tt> so an exception
# 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!(attributes, &block)
find_by(attributes) || create!(attributes, &block)
end
# Like <tt>find_or_create_by</tt>, but calls <tt>new</tt> instead of <tt>create</tt>.
# 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(attributes, &block)
find_by(attributes) || new(attributes, &block)
end
......@@ -304,7 +310,7 @@ def many?
# the existing records is updated or deleted, the cache key changes.
#
# Product.where("name like ?", "%Cosmic Encounter%").cache_key
# => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
# # => "products/query-1850ab3d302391b85b8693e941286659-1-20150714212553907087000"
#
# If the collection is loaded, the method will iterate through the records
# to generate the timestamp, otherwise it will trigger one SQL query like:
......@@ -341,8 +347,8 @@ def scoping
# 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. Values passed to `update_all` will not go through
# ActiveRecord's type-casting behavior. It should receive only values that can be passed as-is to the SQL
# trigger Active Record callbacks or validations. Values passed to #update_all will not go through
# Active Record's type-casting behavior. It should receive only values that can be passed as-is to the SQL
# database.
#
# ==== Parameters
......@@ -403,7 +409,7 @@ def update_all(updates)
# Note: Updating a large number of records will run an
# UPDATE query for each record, which may cause a performance
# issue. So if it is not needed to run callbacks for each update, it is
# preferred to use <tt>update_all</tt> for updating all records using
# preferred to use #update_all for updating all records using
# a single query.
def update(id = :all, attributes)
if id.is_a?(Array)
......@@ -418,9 +424,9 @@ def update(id = :all, attributes)
end
# Destroys the records by instantiating each
# record and calling its +destroy+ method. Each object's callbacks are
# executed (including <tt>:dependent</tt> association options). Returns the
# collection of objects that were destroyed; each will be frozen, to
# record and calling its {#destroy}[rdoc-ref:Persistence#destroy] method.
# Each object's callbacks are executed (including <tt>:dependent</tt> 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
......@@ -428,7 +434,7 @@ def update(id = :all, attributes)
# 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.
# #delete_all instead.
#
# ==== Examples
#
......@@ -447,7 +453,7 @@ def destroy_all(conditions = nil)
# 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 ActiveRecord#delete but allows cleanup methods and other actions to be run.
# 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.
......@@ -473,9 +479,10 @@ def destroy(id)
end
# Deletes the records without instantiating the records
# first, and hence not calling the +destroy+ method nor invoking callbacks. This
# is a single SQL DELETE statement that goes straight to the database, much more
# efficient than +destroy_all+. Be careful with relations though, in particular
# 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
# <tt>:dependent</tt> rules defined on associations are not honored. Returns the
# number of rows affected.
#
......@@ -483,9 +490,9 @@ def destroy(id)
#
# Both calls delete the affected posts all at once with a single DELETE statement.
# If you need to destroy dependent associations or call your <tt>before_*</tt> or
# +after_destroy+ callbacks, use the +destroy_all+ method instead.
# +after_destroy+ callbacks, use the #destroy_all method instead.
#
# If an invalid method is supplied, +delete_all+ raises an ActiveRecord error:
# If an invalid method is supplied, #delete_all raises an ActiveRecordError:
#
# Post.limit(100).delete_all
# # => ActiveRecord::ActiveRecordError: delete_all doesn't support limit
......@@ -534,7 +541,7 @@ def delete_all(conditions = nil)
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
#
# Note: Although it is often much faster than the alternative,
# <tt>#destroy</tt>, skipping callbacks might bypass business logic in
# #destroy, skipping callbacks might bypass business logic in
# your application that ensures referential integrity or performs other
# essential jobs.
#
......@@ -624,8 +631,10 @@ def joined_includes_values
includes_values & joins_values
end
# +uniq+ and +uniq!+ are silently deprecated. +uniq_value+ delegates to +distinct_value+
# to maintain backwards compatibility. Use +distinct_value+ instead.
# {#uniq}[rdoc-ref:QueryMethods#uniq] and
# {#uniq!}[rdoc-ref:QueryMethods#uniq!] are silently deprecated.
# #uniq_value delegates to #distinct_value to maintain backwards compatibility.
# Use #distinct_value instead.
def uniq_value
distinct_value
end
......
......@@ -3,8 +3,8 @@
module ActiveRecord
module Batches
# 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.
# (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.
......
......@@ -14,33 +14,34 @@ module Calculations
# Person.distinct.count(:age)
# # => counts the number of different age values
#
# If +count+ is used with +group+, it returns a Hash whose keys represent the aggregated column,
# 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 +group+ for multiple columns, it returns a Hash whose
# 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+.
# 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 +select+, it will count the selected columns:
# 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 +select+ expressions are valid +count+ expressions. The specifics differ
# 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(column_name = nil)
calculate(:count, column_name)
end
# Calculates the average value on a given column. Returns +nil+ if there's
# no row. See +calculate+ for examples with options.
# no row. See #calculate for examples with options.
#
# Person.average(:age) # => 35.8
def average(column_name)
......@@ -49,7 +50,7 @@ def average(column_name)
# Calculates the minimum value on a given column. The value is returned
# with the same data type of the column, or +nil+ if there's no row. See
# +calculate+ for examples with options.
# #calculate for examples with options.
#
# Person.minimum(:age) # => 7
def minimum(column_name)
......@@ -58,7 +59,7 @@ def minimum(column_name)
# Calculates the maximum value on a given column. The value is returned
# with the same data type of the column, or +nil+ if there's no row. See
# +calculate+ for examples with options.
# #calculate for examples with options.
#
# Person.maximum(:age) # => 93
def maximum(column_name)
......@@ -66,8 +67,8 @@ def maximum(column_name)
end
# 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.
# 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(column_name = nil, &block)
......@@ -75,8 +76,8 @@ def sum(column_name = nil, &block)
calculate(:sum, column_name)
end
# This calculates aggregate values in the given column. Methods for count, sum, average,
# minimum, and maximum have been added as shortcuts.
# 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...
......@@ -118,7 +119,7 @@ def calculate(operation, column_name)
end
end
# Use <tt>pluck</tt> as a shortcut to select one or more attributes without
# 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)
......@@ -127,7 +128,7 @@ def calculate(operation, column_name)
#
# Person.all.map(&:name)
#
# Pluck returns an <tt>Array</tt> of attribute values type-casted to match
# 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.
#
......@@ -151,7 +152,7 @@ def calculate(operation, column_name)
# # SELECT DATEDIFF(updated_at, created_at) FROM people
# # => ['0', '27761', '173']
#
# See also +ids+.
# See also #ids.
#
def pluck(*column_names)
column_names.map! do |column_name|
......
......@@ -17,7 +17,7 @@ module FinderMethods
# Person.where("administrator = 1").order("created_on DESC").find(1)
#
# NOTE: The returned records may not be in the same order as the ids you
# provide since database rows are unordered. You'd need to provide an explicit <tt>order</tt>
# provide since database rows are unordered. You'd need to provide an explicit QueryMethods#order
# option if you want the results are sorted.
#
# ==== Find with lock
......@@ -34,7 +34,7 @@ module FinderMethods
# person.save!
# end
#
# ==== Variations of +find+
# ==== Variations of #find
#
# Person.where(name: 'Spartacus', rating: 4)
# # returns a chainable list (which can be empty).
......@@ -48,7 +48,7 @@ module FinderMethods
# Person.where(name: 'Spartacus', rating: 4).first_or_create
# # returns the first item or creates it and returns it.
#
# ==== Alternatives for +find+
# ==== Alternatives for #find
#
# Person.where(name: 'Spartacus', rating: 4).exists?(conditions = :none)
# # returns a boolean indicating if any record with the given conditions exist.
......@@ -80,8 +80,8 @@ def find_by(arg, *args)
nil
end
# Like <tt>find_by</tt>, except that if no record is found, raises
# an <tt>ActiveRecord::RecordNotFound</tt> error.
# Like #find_by, except that if no record is found, raises
# an ActiveRecord::RecordNotFound error.
def find_by!(arg, *args)
where(arg, *args).take!
rescue RangeError
......@@ -100,8 +100,8 @@ def take(limit = nil)
limit ? limit(limit).to_a : find_take
end
# Same as +take+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# is found. Note that <tt>take!</tt> accepts no arguments.
# Same as #take but raises ActiveRecord::RecordNotFound if no record
# is found. Note that #take! accepts no arguments.
def take!
take or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql(@klass.arel_engine)}]")
end
......@@ -123,8 +123,8 @@ def first(limit = nil)
end
end
# Same as +first+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# is found. Note that <tt>first!</tt> accepts no arguments.
# Same as #first but raises ActiveRecord::RecordNotFound if no record
# is found. Note that #first! accepts no arguments.
def first!
find_nth! 0
end
......@@ -156,8 +156,8 @@ def last(limit = nil)
end
end
# Same as +last+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# is found. Note that <tt>last!</tt> accepts no arguments.
# Same as #last but raises ActiveRecord::RecordNotFound if no record
# is found. Note that #last! accepts no arguments.
def last!
last or raise RecordNotFound.new("Couldn't find #{@klass.name} with [#{arel.where_sql(@klass.arel_engine)}]")
end
......@@ -172,7 +172,7 @@ def second
find_nth(1, offset_index)
end
# Same as +second+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# Same as #second but raises ActiveRecord::RecordNotFound if no record
# is found.
def second!
find_nth! 1
......@@ -188,7 +188,7 @@ def third
find_nth(2, offset_index)
end
# Same as +third+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# Same as #third but raises ActiveRecord::RecordNotFound if no record
# is found.
def third!
find_nth! 2
......@@ -204,7 +204,7 @@ def fourth
find_nth(3, offset_index)
end
# Same as +fourth+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# Same as #fourth but raises ActiveRecord::RecordNotFound if no record
# is found.
def fourth!
find_nth! 3
......@@ -220,7 +220,7 @@ def fifth
find_nth(4, offset_index)
end
# Same as +fifth+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# Same as #fifth but raises ActiveRecord::RecordNotFound if no record
# is found.
def fifth!
find_nth! 4
......@@ -236,14 +236,14 @@ def forty_two
find_nth(41, offset_index)
end
# Same as +forty_two+ but raises <tt>ActiveRecord::RecordNotFound</tt> if no record
# Same as #forty_two but raises ActiveRecord::RecordNotFound if no record
# is found.
def forty_two!
find_nth! 41
end
# 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:
# 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
......@@ -256,7 +256,7 @@ def forty_two!
# * No args - Returns +false+ if the table is empty, +true+ otherwise.
#
# For more information about specifying conditions as a hash or array,
# see the Conditions section in the introduction to <tt>ActiveRecord::Base</tt>.
# see the Conditions section in the introduction to ActiveRecord::Base.
#
# Note: You can't pass in a condition as a string (like <tt>name =
# 'Jamie'</tt>), since it would be sanitized and then queried against
......@@ -298,7 +298,7 @@ def exists?(conditions = :none)
end
# This method is called whenever no records are found with either a single
# id or multiple ids and raises a +ActiveRecord::RecordNotFound+ exception.
# id or multiple ids and raises a ActiveRecord::RecordNotFound exception.
#
# The error message is different depending on whether a single id or
# multiple ids are provided. If multiple ids are provided, then the number
......
......@@ -20,7 +20,7 @@ def initialize(scope)
# 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 #where for
# #not accepts conditions as a string, array, or hash. See QueryMethods#where for
# more details on each format.
#
# User.where.not("name = 'Jon'")
......@@ -112,7 +112,7 @@ def create_with_value # :nodoc:
#
# 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+.
# performance improvement over a simple join.
#
# You can also specify multiple relationships, like this:
#
......@@ -133,7 +133,7 @@ def create_with_value # :nodoc:
#
# User.includes(:posts).where('posts.name = ?', 'example').references(:posts)
#
# Note that +includes+ works with association names while +references+ needs
# Note that #includes works with association names while #references needs
# the actual table name.
def includes(*args)
check_if_method_has_arguments!(:includes, args)
......@@ -164,7 +164,7 @@ def eager_load!(*args) # :nodoc:
self
end
# Allows preloading of +args+, in the same way that +includes+ does:
# 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)
......@@ -180,7 +180,7 @@ def preload!(*args) # :nodoc:
# 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+.
# This method only works in conjunction with #includes.
# See #includes for more details.
#
# User.includes(:posts).where("posts.name = 'foo'")
......@@ -203,12 +203,12 @@ def references!(*table_names) # :nodoc:
# Works in two unique ways.
#
# First: takes a block so it can be used just like Array#select.
# 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.
# 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:
......@@ -236,7 +236,7 @@ def references!(*table_names) # :nodoc:
# # => "value"
#
# Accessing attributes of an object that do not have fields retrieved by a select
# except +id+ will throw <tt>ActiveModel::MissingAttributeError</tt>:
# except +id+ will throw ActiveModel::MissingAttributeError:
#
# Model.select(:field).first.other_field
# # => ActiveModel::MissingAttributeError: missing attribute: other_field
......@@ -357,15 +357,15 @@ def reorder!(*args) # :nodoc:
# 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.
# 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:
# +: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 <tt>except</tt>, but unlike
# <tt>except</tt>, it persists across merges:
# This method is similar to #except, but unlike
# #except, it persists across merges:
#
# User.order('email').merge(User.except(:order))
# == User.order('email')
......@@ -471,7 +471,7 @@ def joins!(*args) # :nodoc:
# 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 <tt>Kernel::sprintf</tt>.
# 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';
......@@ -575,6 +575,8 @@ def where!(opts, *rest) # :nodoc:
# Post.where(active: true).where(trashed: true).rewhere(trashed: false)
# # WHERE `active` = 1 AND `trashed` = 0
#
# This is short-hand for <tt>unscope(where: conditions.keys).where(conditions)</tt>.
# Note that unlike reorder, we're only unscoping the named conditions -- not the entire where statement.
def rewhere(conditions)
unscope(where: conditions.keys).where(conditions)
end
......@@ -583,8 +585,8 @@ def rewhere(conditions)
# 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.
# 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("id = 2"))
# # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'id = 2'))
......@@ -651,7 +653,7 @@ def offset!(value) # :nodoc:
end
# Specifies locking settings (default to +true+). For more information
# on locking, please see +ActiveRecord::Locking+.
# on locking, please see ActiveRecord::Locking.
def lock(locks = true)
spawn.lock!(locks)
end
......@@ -727,7 +729,7 @@ def readonly!(value = true) # :nodoc:
# users = users.create_with(name: 'DHH')
# users.new.name # => 'DHH'
#
# You can pass +nil+ to +create_with+ to reset attributes:
# You can pass +nil+ to #create_with to reset attributes:
#
# users = users.create_with(nil)
# users.new.name # => 'Oscar'
......
......@@ -10,7 +10,7 @@ def spawn #:nodoc:
clone
end
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an <tt>ActiveRecord::Relation</tt>.
# Merges in the conditions from <tt>other</tt>, if <tt>other</tt> is an ActiveRecord::Relation.
# Returns an array representing the intersection of the resulting records with <tt>other</tt>, if <tt>other</tt> is an array.
# Post.where(published: true).joins(:comments).merge( Comment.where(spam: false) )
# # Performs a single join query with both where conditions.
......
module ActiveRecord
###
# This class encapsulates a Result returned from calling +exec_query+ on any
# database connection adapter. For example:
# 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 # => #<ActiveRecord::Result:0xdeadbeef>
......
......@@ -7,7 +7,7 @@ module ActiveRecord
#
# returns the connection handler local to the current thread.
#
# See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
# See the documentation of ActiveSupport::PerThreadRegistry
# for further details.
class RuntimeRegistry # :nodoc:
extend ActiveSupport::PerThreadRegistry
......
......@@ -3,7 +3,8 @@ module Sanitization
extend ActiveSupport::Concern
module ClassMethods
# Used to sanitize objects before they're used in an SQL SELECT statement. Delegates to <tt>connection.quote</tt>.
# Used to sanitize objects before they're used in an SQL SELECT statement.
# Delegates to {connection.quote}[rdoc-ref:ConnectionAdapters::Quoting#quote].
def sanitize(object) # :nodoc:
connection.quote(object)
end
......@@ -53,8 +54,8 @@ def sanitize_sql_for_assignment(assignments, default_table_name = self.table_nam
end
# Accepts a hash of SQL conditions and replaces those attributes
# that correspond to a +composed_of+ relationship with their expanded
# aggregate attribute values.
# that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
# relationship with their expanded aggregate attribute values.
#
# Given:
#
......
module ActiveRecord
# = Active Record Schema
# = 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
......@@ -30,8 +30,9 @@ module ActiveRecord
class Schema < Migration
# Eval the given block. All methods available to the current connection
# adapter are available within the block, so you can easily use the
# database definition DSL to build up your schema (+create_table+,
# +add_index+, etc.).
# 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):
......
......@@ -59,8 +59,8 @@ def initialize_internals_callback # :nodoc:
#
# 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+
# 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,
......
......@@ -55,7 +55,7 @@ def before_remove_const #:nodoc:
#
# Article.all # => SELECT * FROM articles WHERE published = true
#
# The +default_scope+ is also applied while creating/building a record.
# The #default_scope is also applied while creating/building a record.
# It is not applied while updating a record.
#
# Article.new.published # => true
......@@ -65,7 +65,7 @@ def before_remove_const #:nodoc:
# +default_scope+ macro, and it will be called when building the
# default scope.)
#
# If you use multiple +default_scope+ declarations in your model then
# If you use multiple #default_scope declarations in your model then
# they will be merged together:
#
# class Article < ActiveRecord::Base
......@@ -76,7 +76,7 @@ def before_remove_const #:nodoc:
# Article.all # => SELECT * FROM articles WHERE published = true AND rating = 'G'
#
# This is also the case with inheritance and module includes where the
# parent or module defines a +default_scope+ and the child or including
# parent or module defines a #default_scope and the child or including
# class defines a second one.
#
# If you need to do more complex things with a default scope, you can
......
......@@ -9,7 +9,7 @@ module Named
extend ActiveSupport::Concern
module ClassMethods
# Returns an <tt>ActiveRecord::Relation</tt> scope object.
# Returns an ActiveRecord::Relation scope object.
#
# posts = Post.all
# posts.size # Fires "select count(*) from posts" and returns the count
......@@ -20,7 +20,7 @@ module ClassMethods
# fruits = fruits.limit(10) if limited?
#
# You can define a scope that applies to all finders using
# <tt>ActiveRecord::Base.default_scope</tt>.
# {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
def all
if current_scope
current_scope.clone
......@@ -40,9 +40,10 @@ def default_scoped # :nodoc:
end
# Adds a class method for retrieving and querying objects.
# The method is intended to return an <tt>ActiveRecord::Relation</tt>
# The method is intended to return an ActiveRecord::Relation
# object, which is composable with other scopes.
# If it returns +nil+ or +false+, an <tt>all</tt> scope is returned instead.
# 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
# <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>.
......@@ -52,12 +53,12 @@ def default_scoped # :nodoc:
# scope :dry_clean_only, -> { joins(:washing_instructions).where('washing_instructions.dry_clean_only = ?', true) }
# end
#
# The above calls to +scope+ define class methods <tt>Shirt.red</tt> and
# The above calls to #scope define class methods <tt>Shirt.red</tt> and
# <tt>Shirt.dry_clean_only</tt>. <tt>Shirt.red</tt>, in effect,
# represents the query <tt>Shirt.where(color: 'red')</tt>.
#
# You should always pass a callable object to the scopes defined
# with +scope+. This ensures that the scope is re-evaluated each
# 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
......@@ -70,15 +71,15 @@ def default_scoped # :nodoc:
# end
#
# Unlike <tt>Shirt.find(...)</tt>, however, the object returned by
# <tt>Shirt.red</tt> is not an Array but an <tt>ActiveRecord::Relation</tt>,
# <tt>Shirt.red</tt> is not an Array but an ActiveRecord::Relation,
# which is composable with other scopes; it resembles the association object
# constructed by a +has_many+ declaration. For instance, you can invoke
# <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
# constructed by a {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
# declaration. For instance, you can invoke <tt>Shirt.red.first</tt>, <tt>Shirt.red.count</tt>,
# <tt>Shirt.red.where(size: 'small')</tt>. Also, just as with the
# association objects, named \scopes act like an Array, implementing
# Enumerable; <tt>Shirt.red.each(&block)</tt>, <tt>Shirt.red.first</tt>,
# and <tt>Shirt.red.inject(memo, &block)</tt> all behave as if
# <tt>Shirt.red</tt> really was an Array.
# <tt>Shirt.red</tt> really was an array.
#
# These named \scopes are composable. For instance,
# <tt>Shirt.red.dry_clean_only</tt> will produce all shirts that are
......@@ -89,7 +90,8 @@ def default_scoped # :nodoc:
#
# All scopes are available as class methods on the ActiveRecord::Base
# descendant upon which the \scopes were defined. But they are also
# available to +has_many+ associations. If,
# available to {has_many}[rdoc-ref:Associations::ClassMethods#has_many]
# associations. If,
#
# class Person < ActiveRecord::Base
# has_many :shirts
......@@ -98,8 +100,8 @@ def default_scoped # :nodoc:
# then <tt>elton.shirts.red.dry_clean_only</tt> will return all of
# Elton's red, dry clean only shirts.
#
# \Named scopes can also have extensions, just as with +has_many+
# declarations:
# \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
......
......@@ -3,7 +3,7 @@ module SecureToken
extend ActiveSupport::Concern
module ClassMethods
# Example using has_secure_token
# Example using #has_secure_token
#
# # Schema: User(token:string, auth_token:string)
# class User < ActiveRecord::Base
......@@ -18,11 +18,11 @@ module ClassMethods
# 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.
# <tt>SecureRandom::base58</tt> 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
# <tt>validates_uniqueness_of</tt> can. You're encouraged to add a unique index in the database to deal
# with this even more unlikely scenario.
# {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(attribute = :token)
# Load securerandom only when has_secure_token is used.
require 'active_support/core_ext/securerandom'
......
module ActiveRecord #:nodoc:
# = Active Record Serialization
# = Active Record \Serialization
module Serialization
extend ActiveSupport::Concern
include ActiveModel::Serializers::JSON
......
......@@ -7,12 +7,14 @@ module ActiveRecord
# Book.where(name: "my book").where("author_id > 3")
# end
#
# The cached statement is executed by using the +execute+ method:
# The cached statement is executed by using the
# [connection.execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute} method:
#
# cache.execute([], Book, Book.connection)
#
# The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
# Database is queried when +to_a+ is called on the relation.
# The relation returned by the block is cached, and for each
# [execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute}
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
#
# If you want to cache the statement without the values you can use the +bind+ method of the
# block parameter.
......
......@@ -16,7 +16,8 @@ module ActiveRecord
# 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 PostgreSQL specific columns like +hstore+ or +json+ there is no need for
# the serialization provided by +store+. Simply use +store_accessor+ instead to generate
# 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.
#
......@@ -43,7 +44,7 @@ module ActiveRecord
# store_accessor :settings, :privileges, :servants
# end
#
# The stored attribute names can be retrieved using +stored_attributes+.
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
#
# User.stored_attributes[:settings] # [:color, :homepage]
#
......
......@@ -5,7 +5,7 @@ module Tasks # :nodoc:
class DatabaseAlreadyExists < StandardError; end # :nodoc:
class DatabaseNotSupported < StandardError; end # :nodoc:
# <tt>ActiveRecord::Tasks::DatabaseTasks</tt> is a utility class, which encapsulates
# 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 Rake tasks provided by Active Record.
......@@ -26,7 +26,7 @@ class DatabaseNotSupported < StandardError; end # :nodoc:
# * +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:
# Example usage of DatabaseTasks outside Rails could look as such:
#
# include ActiveRecord::Tasks
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
......
module ActiveRecord
# = Active Record Timestamp
# = Active Record \Timestamp
#
# Active Record automatically timestamps create and update operations if the
# table has fields named <tt>created_at/created_on</tt> or
......@@ -17,7 +17,7 @@ module ActiveRecord
#
# Active Record keeps all the <tt>datetime</tt> and <tt>time</tt> columns
# time-zone 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.
# and converted back to the current <tt>Time.zone</tt> when pulled from the database.
#
# This feature can be turned off completely by setting:
#
......
......@@ -17,10 +17,10 @@ module Transactions
# = Active Record Transactions
#
# Transactions are protective blocks where SQL statements are only permanent
# \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
# 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.
......@@ -40,20 +40,20 @@ module Transactions
#
# == Different Active Record classes in a single transaction
#
# Though the transaction class method is called on some Active Record class,
# 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:
# 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.
# The #transaction method is also available as a model instance method.
# For example, you can also do this:
#
# balance.transaction do
......@@ -80,7 +80,8 @@ module Transactions
#
# == +save+ and +destroy+ are automatically wrapped in a transaction
#
# Both +save+ and +destroy+ come wrapped in a transaction that ensures
# 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
......@@ -89,7 +90,7 @@ module Transactions
# 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
# The #after_commit callback is the only one that is triggered once the update
# is committed. See below.
#
# == Exception handling and rolling back
......@@ -98,11 +99,11 @@ module Transactions
# be propagated (after triggering the ROLLBACK), so you should be ready to
# catch those in your application code.
#
# One exception is the <tt>ActiveRecord::Rollback</tt> exception, which will trigger
# 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 <tt>ActiveRecord::StatementInvalid</tt> exceptions
# inside a transaction block. <tt>ActiveRecord::StatementInvalid</tt> exceptions indicate that an
# *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
......@@ -128,11 +129,11 @@ module Transactions
# end
#
# One should restart the entire transaction if an
# <tt>ActiveRecord::StatementInvalid</tt> occurred.
# ActiveRecord::StatementInvalid occurred.
#
# == Nested transactions
#
# +transaction+ calls can be nested. By default, this makes all database
# #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:
#
......@@ -144,7 +145,7 @@ module Transactions
# end
# end
#
# creates both "Kotori" and "Nemu". Reason is the <tt>ActiveRecord::Rollback</tt>
# 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.
......@@ -171,19 +172,19 @@ module Transactions
# http://dev.mysql.com/doc/refman/5.7/en/savepoint.html
# for more information about savepoints.
#
# === Callbacks
# === \Callbacks
#
# There are two types of callbacks associated with committing and rolling back transactions:
# +after_commit+ and +after_rollback+.
# #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
# #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
# #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
......@@ -234,7 +235,7 @@ def after_commit(*args, &block)
# This callback is called after a create, update, or destroy are rolled back.
#
# Please check the documentation of +after_commit+ for options.
# Please check the documentation of #after_commit for options.
def after_rollback(*args, &block)
set_options_for_callbacks!(args)
set_callback(:rollback, :after, *args, &block)
......@@ -323,7 +324,7 @@ def before_committed! # :nodoc:
_run_before_commit_callbacks
end
# Call the +after_commit+ callbacks.
# Call the #after_commit callbacks.
#
# Ensure that it is not called if the object was never persisted (failed create),
# but call it after the commit of a destroyed object.
......@@ -336,7 +337,7 @@ def committed!(should_run_callbacks: true) #:nodoc:
force_clear_transaction_record_state
end
# Call the +after_rollback+ callbacks. The +force_restore_state+ argument indicates if the record
# Call the #after_rollback callbacks. The +force_restore_state+ argument indicates if the record
# state should be rolled back to the beginning or just to the last savepoint.
def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
if should_run_callbacks
......@@ -348,7 +349,7 @@ def rolledback!(force_restore_state: false, should_run_callbacks: true) #:nodoc:
clear_transaction_record_state
end
# Add the record to the current transaction so that the +after_rollback+ and +after_commit+ callbacks
# Add the record to the current transaction so that the #after_rollback and #after_commit callbacks
# can be called.
def add_to_transaction
if has_transactional_callbacks?
......@@ -457,23 +458,23 @@ def has_transactional_callbacks? # :nodoc:
!_rollback_callbacks.empty? || !_commit_callbacks.empty? || !_before_commit_callbacks.empty?
end
# Updates the attributes on this particular ActiveRecord object so that
# if it's associated with a transaction, then the state of the ActiveRecord
# 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
# 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 ActiveRecord object inside of a transaction carries that transaction's
# 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 ActiveRecord object
# the TransactionState, and rolls back or commits the Active Record object
# as appropriate.
#
# Since ActiveRecord objects can be inside multiple transactions, this
# Since Active Record objects can be inside multiple transactions, this
# method recursively goes through the parent of the TransactionState and
# checks if the ActiveRecord object reflects the state of the object.
# checks if the Active Record object reflects the state of the object.
def sync_with_transaction_state
update_attributes_from_transaction_state(@transaction_state)
end
......
......@@ -22,8 +22,8 @@ class << self
delegate :add_modifier, to: :registry
# Add a new type to the registry, allowing it to be referenced as a
# symbol by ActiveRecord::Attributes::ClassMethods#attribute. If your
# type is only meant to be used with a specific database adapter, you can
# 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 <tt>adapter: :postgresql</tt>. 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. <tt>override: true</tt> will
......
module ActiveRecord
# = Active Record RecordInvalid
# = Active Record \RecordInvalid
#
# Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.
# 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!
......@@ -25,26 +26,26 @@ def initialize(record = nil)
end
end
# = Active Record Validations
# = Active Record \Validations
#
# Active Record includes the majority of its validations from <tt>ActiveModel::Validations</tt>
# Active Record includes the majority of its validations from ActiveModel::Validations
# all of which accept the <tt>:on</tt> argument to define the context where the
# validations are active. Active Record will always supply either the context of
# <tt>:create</tt> or <tt>:update</tt> dependent on whether the model is a
# <tt>new_record?</tt>.
# {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 <tt>validate: false</tt>.
# The regular Base#save method is replaced with this when the validations
# module is mixed in, which it is by default.
# 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(options={})
perform_validations(options) ? super : false
end
# Attempts to save the record just like Base#save but will raise a +RecordInvalid+
# exception instead of returning +false+ if the record is not valid.
# Attempts to save the record just like {ActiveRecord::Base#save}[rdoc-ref:Base#save] but
# will raise a ActiveRecord::RecordInvalid exception instead of returning +false+ if the record is not valid.
def save!(options={})
perform_validations(options) ? super : raise_validation_error
end
......@@ -52,12 +53,12 @@ def save!(options={})
# Runs all the validations within the specified context. Returns +true+ if
# no errors are found, +false+ otherwise.
#
# Aliased as validate.
# Aliased as #validate.
#
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
# <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
# {new_record?}[rdoc-ref:Persistence#new_record?] is +true+, and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
# \Validations with no <tt>:on</tt> option will run no matter the context. \Validations with
# some <tt>:on</tt> option will only run in the specified context.
def valid?(context = nil)
context ||= default_validation_context
......
......@@ -24,7 +24,8 @@ module ClassMethods
#
# 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+.
# guaranteed to be valid, you also need to use
# {validates_presence_of}[rdoc-ref:Validations::ClassMethods#validates_presence_of].
#
# Configuration options:
#
......
......@@ -31,7 +31,7 @@ module ClassMethods
# This is due to the way Object#blank? handles boolean values:
# <tt>false.blank? # => true</tt>.
#
# This validator defers to the ActiveModel validation for presence, adding the
# 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
......@@ -39,7 +39,8 @@ module ClassMethods
#
# 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+.
# it is both present and valid, you also need to use
# {validates_associated}[rdoc-ref:Validations::ClassMethods#validates_associated].
#
# Configuration options:
# * <tt>:message</tt> - A custom error message (default is: "can't be blank").
......@@ -57,7 +58,7 @@ module ClassMethods
# or <tt>unless: Proc.new { |user| user.signup_step <= 2 }</tt>). The method,
# proc or string should return or evaluate to a +true+ or +false+ value.
# * <tt>:strict</tt> - Specifies whether validation should be strict.
# See <tt>ActiveModel::Validation#validates!</tt> for more information.
# See ActiveModel::Validation#validates! for more information.
def validates_presence_of(*attr_names)
validates_with PresenceValidator, _merge_attributes(attr_names)
end
......
......@@ -172,7 +172,8 @@ module ClassMethods
#
# === Concurrency and integrity
#
# Using this validation method in conjunction with ActiveRecord::Base#save
# 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
......@@ -209,12 +210,12 @@ module ClassMethods
# This could even happen if you use transactions with the 'serializable'
# isolation level. The best way to work around this problem is to add a unique
# index to the database table using
# ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the
# rare case that a race condition occurs, the database will guarantee
# {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 will raise an ActiveRecord::StatementInvalid
# {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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册