2017-07-09 17:41:28 +00:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2004-11-24 01:04:44 +00:00
|
|
|
#--
|
2021-01-01 03:21:20 +00:00
|
|
|
# Copyright (c) 2004-2021 David Heinemeier Hansson
|
2004-11-24 01:04:44 +00:00
|
|
|
#
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
|
|
# a copy of this software and associated documentation files (the
|
|
|
|
# "Software"), to deal in the Software without restriction, including
|
|
|
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
|
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
|
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
|
|
# the following conditions:
|
|
|
|
#
|
|
|
|
# The above copyright notice and this permission notice shall be
|
|
|
|
# included in all copies or substantial portions of the Software.
|
|
|
|
#
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
|
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
|
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
|
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
#++
|
|
|
|
|
2016-08-06 16:24:04 +00:00
|
|
|
require "active_support"
|
|
|
|
require "active_support/rails"
|
|
|
|
require "active_model"
|
|
|
|
require "arel"
|
2017-10-19 16:45:07 +00:00
|
|
|
require "yaml"
|
2009-10-15 02:05:06 +00:00
|
|
|
|
2017-10-21 13:17:03 +00:00
|
|
|
require "active_record/version"
|
2017-10-19 16:45:07 +00:00
|
|
|
require "active_model/attribute_set"
|
Stop autoloading AbstractAdapter prematurely
In 7254d23764f7abe8023f3daeb07d99ea1c8e777a, an autoload for
`ConnectionAdapters::AbstractAdapter` was added to `active_record.rb`.
Later in d6b923adbdfc9a4df20132f741bbfb43db12113c, a manual require for
that class was added to `active_record/base.rb` as some constants under
`ConnectionAdapters` weren't defined until `AbstractAdapter` was loaded.
In 1efd88283ef68d912df215125951a87526768a51, the require was removed and
replaced with an autoload in `active_record.rb`, above the previous one.
Because the first autoload was for the `ConnectionAdapters` constant and
the second one tried to create it, the autoload would fire immediately.
Rather than fixing the autoload problem, the require had effectively
just been moved from `active_record/base.rb` to `active_record.rb`.
Instead of defining autoloads for constants under `ConnectionAdapters`
in the `abstract_adapter.rb` file, we can create a separate, autoloaded
`connection_adapters.rb` file for this purpose.
To avoid a "circular require considered harmful" warning from Ruby, we
have to fix the module nesting in `schema_creation.rb`, as a followup to
e4108fc619e0f1c28cdec6049d31f2db01d56dfd.
`AbstractAdapter` loads many other dependencies, so making it autoload
properly has a noticeable impact on the load time of `active_record.rb`.
Benchmark:
$ cat test.rb
require "bundler/setup"
before = ObjectSpace.each_object(Module).count
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
require "active_record"
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
after = ObjectSpace.each_object(Module).count
puts "took #{finish - start} and created #{after - before} modules"
Before:
$ ruby test.rb
took 0.47532399999909103 and created 901 modules
After:
$ ruby test.rb
took 0.3299509999342263 and created 608 modules
2019-09-12 22:02:35 +00:00
|
|
|
require "active_record/errors"
|
2010-10-10 23:11:04 +00:00
|
|
|
|
2008-11-24 17:14:24 +00:00
|
|
|
module ActiveRecord
|
2009-12-03 04:01:01 +00:00
|
|
|
extend ActiveSupport::Autoload
|
2004-11-24 01:04:44 +00:00
|
|
|
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Base
|
|
|
|
autoload :Callbacks
|
|
|
|
autoload :Core
|
|
|
|
autoload :ConnectionHandling
|
2013-04-05 06:21:48 +00:00
|
|
|
autoload :CounterCache
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :DynamicMatchers
|
2020-05-23 22:14:40 +00:00
|
|
|
autoload :DelegatedType
|
2021-02-23 18:02:10 +00:00
|
|
|
autoload :Encryption
|
2013-11-02 19:01:31 +00:00
|
|
|
autoload :Enum
|
2015-08-14 16:31:33 +00:00
|
|
|
autoload :InternalMetadata
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Explain
|
|
|
|
autoload :Inheritance
|
|
|
|
autoload :Integration
|
|
|
|
autoload :Migration
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload :Migrator, "active_record/migration"
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :ModelSchema
|
|
|
|
autoload :NestedAttributes
|
2013-11-05 12:44:16 +00:00
|
|
|
autoload :NoTouching
|
2015-03-13 17:14:55 +00:00
|
|
|
autoload :TouchLater
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Persistence
|
|
|
|
autoload :QueryCache
|
|
|
|
autoload :Querying
|
|
|
|
autoload :ReadonlyAttributes
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload :RecordInvalid, "active_record/validations"
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Reflection
|
2013-04-09 20:29:36 +00:00
|
|
|
autoload :RuntimeRegistry
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Sanitization
|
|
|
|
autoload :Schema
|
|
|
|
autoload :SchemaDumper
|
|
|
|
autoload :SchemaMigration
|
|
|
|
autoload :Scoping
|
|
|
|
autoload :Serialization
|
|
|
|
autoload :Store
|
2020-05-17 18:19:37 +00:00
|
|
|
autoload :SignedId
|
2015-02-18 22:55:48 +00:00
|
|
|
autoload :Suppressor
|
2012-08-03 00:43:26 +00:00
|
|
|
autoload :Timestamp
|
|
|
|
autoload :Transactions
|
|
|
|
autoload :Translation
|
|
|
|
autoload :Validations
|
2014-12-28 22:24:10 +00:00
|
|
|
autoload :SecureToken
|
2019-01-09 13:36:29 +00:00
|
|
|
autoload :DestroyAssociationAsyncJob
|
2012-08-03 00:43:26 +00:00
|
|
|
|
2009-12-22 23:27:37 +00:00
|
|
|
eager_autoload do
|
2021-04-15 22:09:21 +00:00
|
|
|
autoload :StatementCache
|
Stop autoloading AbstractAdapter prematurely
In 7254d23764f7abe8023f3daeb07d99ea1c8e777a, an autoload for
`ConnectionAdapters::AbstractAdapter` was added to `active_record.rb`.
Later in d6b923adbdfc9a4df20132f741bbfb43db12113c, a manual require for
that class was added to `active_record/base.rb` as some constants under
`ConnectionAdapters` weren't defined until `AbstractAdapter` was loaded.
In 1efd88283ef68d912df215125951a87526768a51, the require was removed and
replaced with an autoload in `active_record.rb`, above the previous one.
Because the first autoload was for the `ConnectionAdapters` constant and
the second one tried to create it, the autoload would fire immediately.
Rather than fixing the autoload problem, the require had effectively
just been moved from `active_record/base.rb` to `active_record.rb`.
Instead of defining autoloads for constants under `ConnectionAdapters`
in the `abstract_adapter.rb` file, we can create a separate, autoloaded
`connection_adapters.rb` file for this purpose.
To avoid a "circular require considered harmful" warning from Ruby, we
have to fix the module nesting in `schema_creation.rb`, as a followup to
e4108fc619e0f1c28cdec6049d31f2db01d56dfd.
`AbstractAdapter` loads many other dependencies, so making it autoload
properly has a noticeable impact on the load time of `active_record.rb`.
Benchmark:
$ cat test.rb
require "bundler/setup"
before = ObjectSpace.each_object(Module).count
start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
require "active_record"
finish = Process.clock_gettime(Process::CLOCK_MONOTONIC)
after = ObjectSpace.each_object(Module).count
puts "took #{finish - start} and created #{after - before} modules"
Before:
$ ruby test.rb
took 0.47532399999909103 and created 901 modules
After:
$ ruby test.rb
took 0.3299509999342263 and created 608 modules
2019-09-12 22:02:35 +00:00
|
|
|
autoload :ConnectionAdapters
|
2011-08-16 14:01:18 +00:00
|
|
|
|
2012-07-27 21:21:29 +00:00
|
|
|
autoload :Aggregations
|
2009-12-22 23:27:37 +00:00
|
|
|
autoload :Associations
|
2011-12-15 20:07:41 +00:00
|
|
|
autoload :AttributeAssignment
|
2013-04-05 06:21:48 +00:00
|
|
|
autoload :AttributeMethods
|
2009-12-22 23:27:37 +00:00
|
|
|
autoload :AutosaveAssociation
|
Allow Adapter#select_all to be performed asynchronously from a background thread pool
Sometimes a controller or a job has to perform multiple independent queries, e.g.:
```
def index
@posts = Post.published
@categories = Category.active
end
```
Since these two queries are totally independent, ideally you could
execute them in parallel, so that assuming that each take 50ms, the
total query time would be 50ms rather than 100ms.
A very naive way to do this is to simply call `Relation#to_a` in a
background thread, the problem is that most Rails applications, and
even Rails itself rely on thread local state (`PerThreadRegistry`,
`CurrentAttributes`, etc). So executing such a high level interface
from another thread is likely to lead to many context loss problems
or even thread safety issues.
What we can do instead, is to schedule a much lower level operation
(`Adapter#select_all`) in a thread pool, and return a future/promise.
This way we kepp most of the risky code on the main thread, but perform
the slow IO in background, with very little chance of executing some
code that rely on state stored in thread local storage.
Also since most users are on MRI, only the IO can really be parallelized,
so scheduling more code to be executed in background wouldn't lead
to better performance.
2020-08-13 07:54:53 +00:00
|
|
|
autoload :AsynchronousQueriesTracker
|
2009-12-30 07:58:26 +00:00
|
|
|
|
2017-01-31 05:19:51 +00:00
|
|
|
autoload :LegacyYamlAdapter
|
|
|
|
|
2009-12-22 23:27:37 +00:00
|
|
|
autoload :Relation
|
2013-04-25 20:37:44 +00:00
|
|
|
autoload :AssociationRelation
|
Add option to skip joins for associations.
In a multiple database application, associations can't join across
databases. When set, this option tells Rails to make 2 or more queries
rather than using joins for associations.
Set the option on a has many through association:
```ruby
class Dog
has_many :treats, through: :humans, disable_joins: true
has_many :humans
end
```
Then instead of generating join SQL, two queries are used for `@dog.treats`:
```
SELECT "humans"."id" FROM "humans" WHERE "humans"."dog_id" = ? [["dog_id", 1]]
SELECT "treats".* FROM "treats" WHERE "treats"."human_id" IN (?, ?, ?) [["human_id", 1], ["human_id", 2], ["human_id", 3]]
```
This code is extracted from a gem we use internally at GitHub which
means the implementation here is used in production daily and isn't
experimental.
I often get the question "why can't Rails do this automatically" so I
figured I'd include the answer in the commit. Rails can't do this
automatically because associations are lazily loaded. `dog.treats` needs
to load `Dog`, then `Human` and then `Treats`. When `dog.treats` is
called Rails pre-generates the SQL that will be run and puts that
information into a reflection object. Because the SQL parts are pre-generated,
as soon as `dog.treats` is loaded it's too late to skip a join. The join
is already available on the object and that join is what's run to load
`treats` from `dog` through `humans`. I think the only way to avoid setting
an option on the association is to rewrite how and when the SQL is
generated for associations which is a large undertaking. Basically the
way that Active Record associations are designed, it is currently
impossible to have Rails figure out to not join (loading the association
will cause the join to occur, and that join will raise an error if the
models don't live in the same db).
The original implementation was written by me and Aaron. Lee helped port
over tests, and I refactored the extraction to better match Rails style.
Co-authored-by: Lee Quarella <leequarella@gmail.com>
Co-authored-by: Aaron Patterson <aaron@rubyonrails.org>
2020-11-03 18:01:41 +00:00
|
|
|
autoload :DisableJoinsAssociationRelation
|
2012-01-30 20:36:47 +00:00
|
|
|
autoload :NullRelation
|
2009-12-30 07:58:26 +00:00
|
|
|
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload_under "relation" do
|
2009-12-30 07:58:26 +00:00
|
|
|
autoload :QueryMethods
|
|
|
|
autoload :FinderMethods
|
2010-01-19 16:45:35 +00:00
|
|
|
autoload :Calculations
|
2009-12-31 21:44:19 +00:00
|
|
|
autoload :PredicateBuilder
|
2010-01-03 13:27:57 +00:00
|
|
|
autoload :SpawnMethods
|
2010-02-12 16:53:51 +00:00
|
|
|
autoload :Batches
|
2011-12-15 19:46:30 +00:00
|
|
|
autoload :Delegation
|
2009-12-30 07:58:26 +00:00
|
|
|
end
|
|
|
|
|
2011-08-16 14:01:18 +00:00
|
|
|
autoload :Result
|
Allow Adapter#select_all to be performed asynchronously from a background thread pool
Sometimes a controller or a job has to perform multiple independent queries, e.g.:
```
def index
@posts = Post.published
@categories = Category.active
end
```
Since these two queries are totally independent, ideally you could
execute them in parallel, so that assuming that each take 50ms, the
total query time would be 50ms rather than 100ms.
A very naive way to do this is to simply call `Relation#to_a` in a
background thread, the problem is that most Rails applications, and
even Rails itself rely on thread local state (`PerThreadRegistry`,
`CurrentAttributes`, etc). So executing such a high level interface
from another thread is likely to lead to many context loss problems
or even thread safety issues.
What we can do instead, is to schedule a much lower level operation
(`Adapter#select_all`) in a thread pool, and return a future/promise.
This way we kepp most of the risky code on the main thread, but perform
the slow IO in background, with very little chance of executing some
code that rely on state stored in thread local storage.
Also since most users are on MRI, only the IO can really be parallelized,
so scheduling more code to be executed in background wouldn't lead
to better performance.
2020-08-13 07:54:53 +00:00
|
|
|
autoload :FutureResult
|
2016-08-15 21:12:08 +00:00
|
|
|
autoload :TableMetadata
|
2017-11-10 21:43:54 +00:00
|
|
|
autoload :Type
|
2009-12-22 23:27:37 +00:00
|
|
|
end
|
2004-11-24 01:04:44 +00:00
|
|
|
|
2011-02-01 17:34:21 +00:00
|
|
|
module Coders
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload :YAMLColumn, "active_record/coders/yaml_column"
|
|
|
|
autoload :JSON, "active_record/coders/json"
|
2011-02-01 17:34:21 +00:00
|
|
|
end
|
|
|
|
|
2009-07-24 05:25:27 +00:00
|
|
|
module AttributeMethods
|
2009-12-03 04:01:01 +00:00
|
|
|
extend ActiveSupport::Autoload
|
|
|
|
|
2009-12-22 23:27:37 +00:00
|
|
|
eager_autoload do
|
|
|
|
autoload :BeforeTypeCast
|
|
|
|
autoload :Dirty
|
|
|
|
autoload :PrimaryKey
|
|
|
|
autoload :Query
|
|
|
|
autoload :Read
|
|
|
|
autoload :TimeZoneConversion
|
|
|
|
autoload :Write
|
2011-11-30 15:52:09 +00:00
|
|
|
autoload :Serialization
|
2009-12-22 23:27:37 +00:00
|
|
|
end
|
2009-07-24 05:25:27 +00:00
|
|
|
end
|
|
|
|
|
2008-11-24 17:14:24 +00:00
|
|
|
module Locking
|
2009-12-03 04:01:01 +00:00
|
|
|
extend ActiveSupport::Autoload
|
2009-12-16 17:56:51 +00:00
|
|
|
|
2009-12-22 23:27:37 +00:00
|
|
|
eager_autoload do
|
|
|
|
autoload :Optimistic
|
|
|
|
autoload :Pessimistic
|
|
|
|
end
|
2008-11-24 17:14:24 +00:00
|
|
|
end
|
2005-05-02 07:04:20 +00:00
|
|
|
|
2011-12-15 20:35:04 +00:00
|
|
|
module Scoping
|
|
|
|
extend ActiveSupport::Autoload
|
|
|
|
|
|
|
|
eager_autoload do
|
|
|
|
autoload :Named
|
|
|
|
autoload :Default
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2019-01-17 18:33:48 +00:00
|
|
|
module Middleware
|
|
|
|
extend ActiveSupport::Autoload
|
|
|
|
|
|
|
|
autoload :DatabaseSelector, "active_record/middleware/database_selector"
|
|
|
|
end
|
|
|
|
|
2012-06-16 23:44:29 +00:00
|
|
|
module Tasks
|
|
|
|
extend ActiveSupport::Autoload
|
|
|
|
|
|
|
|
autoload :DatabaseTasks
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload :SQLiteDatabaseTasks, "active_record/tasks/sqlite_database_tasks"
|
|
|
|
autoload :MySQLDatabaseTasks, "active_record/tasks/mysql_database_tasks"
|
2012-06-17 12:03:32 +00:00
|
|
|
autoload :PostgreSQLDatabaseTasks,
|
2016-08-06 16:24:04 +00:00
|
|
|
"active_record/tasks/postgresql_database_tasks"
|
2012-06-16 23:44:29 +00:00
|
|
|
end
|
|
|
|
|
2017-12-20 21:59:41 +00:00
|
|
|
autoload :TestDatabases, "active_record/test_databases"
|
2016-08-06 16:24:04 +00:00
|
|
|
autoload :TestFixtures, "active_record/fixtures"
|
2012-08-01 18:54:22 +00:00
|
|
|
|
|
|
|
def self.eager_load!
|
|
|
|
super
|
|
|
|
ActiveRecord::Locking.eager_load!
|
|
|
|
ActiveRecord::Scoping.eager_load!
|
|
|
|
ActiveRecord::Associations.eager_load!
|
|
|
|
ActiveRecord::AttributeMethods.eager_load!
|
|
|
|
ActiveRecord::ConnectionAdapters.eager_load!
|
2021-03-12 16:36:49 +00:00
|
|
|
ActiveRecord::Encryption.eager_load!
|
2012-08-01 18:54:22 +00:00
|
|
|
end
|
2010-03-30 00:08:08 +00:00
|
|
|
end
|
2010-03-07 14:24:30 +00:00
|
|
|
|
2010-03-30 00:08:08 +00:00
|
|
|
ActiveSupport.on_load(:active_record) do
|
2010-09-30 23:28:12 +00:00
|
|
|
Arel::Table.engine = self
|
2008-11-24 17:14:24 +00:00
|
|
|
end
|
2008-06-19 14:25:27 +00:00
|
|
|
|
2012-05-10 23:48:23 +00:00
|
|
|
ActiveSupport.on_load(:i18n) do
|
2017-05-15 14:17:28 +00:00
|
|
|
I18n.load_path << File.expand_path("active_record/locale/en.yml", __dir__)
|
2012-05-10 23:48:23 +00:00
|
|
|
end
|
2017-10-19 16:45:07 +00:00
|
|
|
|
|
|
|
YAML.load_tags["!ruby/object:ActiveRecord::AttributeSet"] = "ActiveModel::AttributeSet"
|
|
|
|
YAML.load_tags["!ruby/object:ActiveRecord::Attribute::FromDatabase"] = "ActiveModel::Attribute::FromDatabase"
|
|
|
|
YAML.load_tags["!ruby/object:ActiveRecord::LazyAttributeHash"] = "ActiveModel::LazyAttributeHash"
|
2020-06-25 11:36:47 +00:00
|
|
|
YAML.load_tags["!ruby/object:ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::MysqlString"] = "ActiveRecord::Type::String"
|