| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
| |
Class level `update` and `destroy` are using `find` in the internal, so
it will raise `RecordNotFound` if given ids cannot find an object even
though the method already affect (update or destroy) to any objects.
These methods should return affected objects even in that case.
|
|
|
|
|
|
|
|
|
|
| |
`Persistence::ClassMethods`
The docs are obviously for class level `update`, `destroy`, and
`delete`. It should be placed in `Persistence::ClassMethods` rather than
`Relation`. And also, these methods are not dependent on relation. So it
is not needed to delegate to `all` (plus, `klass.find` is faster than
`relation.find`).
|
| |
|
|
|
|
|
|
|
|
|
| |
given
Related 2b5f5cdd7c1d95716de6a206b6d09ccbb006dc17.
If `reflection.scope` isn't given, `reflection_scope` is always empty
scope. It is unnecessary to merge it.
|
|
|
|
|
|
|
|
|
| |
Related 2b5f5cdd7c1d95716de6a206b6d09ccbb006dc17.
If `through_scope` is empty scope, it is unnecessary to merge it.
And also, comparing relations is a little expensive (will cause
`build_arel`). It is enough to use `empty_scope?` to determine whether
empty scope.
|
|
|
|
| |
`through_scope` is not empty scope if `options[:source_type]` is given.
|
|
|
|
|
|
|
| |
* `rails db:migrate STEP = 2` will not rollback the migrations, instead
`rails db:rollback STEP = 2` will do the rollback.
* Also, rewritten `rails db:migrate VERSION` => `rails db:rollback VERSION`
for consistency.
|
|
|
|
|
|
|
| |
It is only used `primary_key` and `connection` in the internal, so it is
not needed to delegate others to `klass` explicitly.
This doesn't change public behavior because `relation` will delegate
missing method to `klass`.
|
|
|
|
|
| |
Because `collection.table_name` doesn't respect table alias.
Use `collection.arel_attribute` instead.
|
|
|
|
|
|
| |
Because `quoted_table_name` doesn't respect table alias. We should use
`arel_attribute` for that, so I added `column_name_from_arel_node` to
generate column name from an arel node.
|
|
|
|
| |
So using `arel_attribute(primary_key).asc` in `batch_order` instead.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Before:
```sql
SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > 2 ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > 4 ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > 6 ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > 8 ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > 10 ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
```
After:
```sql
SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > ? ORDER BY "posts"."id" ASC LIMIT ? [["id", 2], ["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > ? ORDER BY "posts"."id" ASC LIMIT ? [["id", 4], ["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > ? ORDER BY "posts"."id" ASC LIMIT ? [["id", 6], ["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > ? ORDER BY "posts"."id" ASC LIMIT ? [["id", 8], ["LIMIT", 2]]
SELECT "posts".* FROM "posts" WHERE "posts"."id" > ? ORDER BY "posts"."id" ASC LIMIT ? [["id", 10], ["LIMIT", 2]]
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`ActiveRecord::Associations::Preloader::Association`.
```
require 'active_record'
require 'benchmark/ips'
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.string :name, :email
t.integer :topic_id
t.timestamps null: false
end
create_table :topics, force: true do |t|
t.string :title
t.timestamps null: false
end
end
attributes = {
name: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
email: 'foobar@email.com'
}
class Topic < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :topic
end
100.times do
User.create!(attributes)
end
users = User.first(50)
100.times do
Topic.create!(title: 'This is a topic', users: users)
end
Benchmark.ips do |x|
x.config(time: 10, warmup: 5)
x.report("preload") do
User.includes(:topic).all.to_a
end
end
```
```
Calculating -------------------------------------
preload 25.000 i/100ms
-------------------------------------------------
preload 251.772 (± 1.2%) i/s - 2.525k
```
```
Calculating -------------------------------------
preload 26.000 i/100ms
-------------------------------------------------
preload 270.392 (± 1.1%) i/s - 2.704k
```
|
|\
| |
| | |
PERF: Recover `ActiveRecord::pluck` performance.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
```ruby
require 'active_record'
require 'benchmark/ips'
ActiveRecord::Base.establish_connection(ENV.fetch('DATABASE_URL'))
ActiveRecord::Migration.verbose = false
ActiveRecord::Schema.define do
create_table :users, force: true do |t|
t.string :name, :email
t.timestamps null: false
end
end
attributes = {
name: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
email: 'foobar@email.com'
}
class User < ActiveRecord::Base; end
1000.times do
User.create!(attributes)
end
Benchmark.ips do |x|
x.config(time: 10, warmup: 2)
x.report('pluck 1 column') do
User.pluck(:id)
end
x.report('pluck 2 columns') do
User.pluck(:id, :email)
end
x.report('pluck 1 column with scope') do
User.where(id: 1000).pluck(:id)
end
x.report('pluck 2 columns with scope') do
User.where(id: 1000).pluck(:id, :email)
end
end
```
```
Calculating -------------------------------------
pluck 1 column 122.000 i/100ms
pluck 2 columns 74.000 i/100ms
pluck 1 column with scope
615.000 i/100ms
pluck 2 columns with scope
515.000 i/100ms
-------------------------------------------------
pluck 1 column 1.272k (± 3.9%) i/s - 12.810k
pluck 2 columns 750.096 (± 3.3%) i/s - 7.548k
pluck 1 column with scope
6.074k (± 4.1%) i/s - 60.885k
pluck 2 columns with scope
5.158k (± 2.7%) i/s - 52.015k
```
```
Calculating -------------------------------------
pluck 1 column 126.000 i/100ms
pluck 2 columns 78.000 i/100ms
pluck 1 column with scope
457.000 i/100ms
pluck 2 columns with scope
434.000 i/100ms
-------------------------------------------------
pluck 1 column 1.266k (± 2.1%) i/s - 12.726k
pluck 2 columns 795.061 (± 3.0%) i/s - 7.956k
pluck 1 column with scope
4.660k (± 2.1%) i/s - 46.614k
pluck 2 columns with scope
4.355k (± 2.3%) i/s - 43.834k
```
```
Calculating -------------------------------------
pluck 1 column 126.000 i/100ms
pluck 2 columns 78.000 i/100ms
pluck 1 column with scope
539.000 i/100ms
pluck 2 columns with scope
481.000 i/100ms
-------------------------------------------------
pluck 1 column 1.308k (± 3.4%) i/s - 13.104k
pluck 2 columns 798.604 (± 2.8%) i/s - 8.034k
pluck 1 column with scope
5.530k (± 3.4%) i/s - 55.517k
pluck 2 columns with scope
4.914k (± 2.7%) i/s - 49.543k
```
```
Calculating -------------------------------------
pluck 1 column 139.000 i/100ms
pluck 2 columns 79.000 i/100ms
pluck 1 column with scope
580.000 i/100ms
pluck 2 columns with scope
526.000 i/100ms
-------------------------------------------------
pluck 1 column 1.337k (± 3.0%) i/s - 13.483k
pluck 2 columns 806.776 (± 2.7%) i/s - 8.137k
pluck 1 column with scope
5.924k (± 4.1%) i/s - 59.160k
pluck 2 columns with scope
5.276k (± 3.1%) i/s - 53.126k
```
|
| |
| |
| |
| |
| |
| | |
This method was moved from `JoinHelper` in 0fddc3c1, but it is only used
for `table.create_join` in the internal and `Nodes::InnerJoin` is
default join klass. So it is not needed to pass it explicitly.
|
| |
| |
| |
| |
| | |
The superclass (`MacroReflection`) already have the same method
definition.
|
| |
| |
| |
| |
| | |
`primary_key_type` is no longer used since #26718.
`quoted_table_name` is no longer used since Rails 3.1.
|
| |
| |
| |
| | |
Fixes #30539.
|
| |
| |
| |
| |
| |
| | |
Because `table` is part of `reflection`, don't need to pass it
explicitly. And also, naming `alias_name` to `table` is a little
confusing. `aliased_table` is preferable than `alias_name`.
|
| |
| |
| |
| |
| |
| | |
`PolymorphicReflection` is an internal class that is used in
`ThroughReflection`. But `RuntimeReflection` is used for the head of
chain in `AssociationScope`. These are totally different things.
|
| |
| |
| |
| |
| |
| |
| |
| |
| | |
The order of scope evaluation should be from through scope to the
association's own scope. Otherwise the association's scope cannot affect
to through scope.
Fixes #13677.
Closes #28449.
|
| |
| |
| |
| | |
Because `refl.scope` is the same meaning with `chain_head.scope`.
|
| |
| |
| |
| |
| |
| | |
not empty
Because `reflection_scope.values` will create extra new hash.
|
| |
| |
| |
| |
| | |
If `reflection.scope` isn't given, `reflection_scope` is always
`klass.unscoped`. it is unnecessary to merge it.
|
|/
|
|
|
|
|
| |
Otherwise using reserved words as composite primary key names will be
failed as an invalid SQL.
Fixes #30518.
|
|
|
|
|
|
|
|
| |
Defined scope treats nil as `all`, but scope in associations isn't so.
If the result of the scope is nil, most features on associations will be
broken. It should treat nil as `all` like defined scope.
Fixes #20823.
|
|
|
|
|
|
|
|
|
|
| |
If `reflection_scope.where_clause` is not empty, `through_scope` should
be joined the source association. But if `values[:references]` in
`reflection_scope` is empty, the source association will not be joined.
It should use `source_reflection.table_name` in that case.
Fixes #22535.
Closes #28763.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Without this fix, preloading `:comments_with_include` will cause the
following error:
```
% bundle exec ruby -w -Itest test/cases/associations/eager_test.rb -n test_eager_with_has_many_through_join_model_with_include
Using sqlite3
Run options: -n test_eager_with_has_many_through_join_model_with_include --seed 1502
E
Error:
EagerAssociationTest#test_eager_with_has_many_through_join_model_with_include:
ActiveRecord::AssociationNotFoundError: Association named 'post' was not found on Post; perhaps you misspelled it?
```
|
|
|
|
|
| |
If `reflection_scope.where_clause` is empty, `scope` isn't changed. So
`scope.eager_loading?` is always false.
|
|
|
|
|
|
| |
type columns
Fixes #30496.
|
|
|
|
|
|
|
|
|
| |
Don't use remove_method or remove_possible_method just before a new
definition: at best the purpose is unclear, and at worst it creates a
race condition.
Instead, prefer redefine_method when practical, and
silence_redefinition_of_method otherwise.
|
|\
| |
| | |
Delegate :rindex, :slice, :rotate(missing) to 'records'
|
| | |
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Without this, `db:structure:dump` task raises an error as follwing:
```
can't modify frozen String
activerecord/lib/active_record/tasks/sqlite_database_tasks.rb:77:in `run_cmd_error'
activerecord/lib/active_record/tasks/sqlite_database_tasks.rb:72:in `run_cmd'
activerecord/lib/active_record/tasks/sqlite_database_tasks.rb:52:in `structure_dump'
activerecord/lib/active_record/tasks/database_tasks.rb:219:in `structure_dump'
activerecord/lib/active_record/railties/databases.rake:279:in `block (3 levels) in <main>'
railties/lib/rails/commands/rake/rake_command.rb:23:in `block in perform'
railties/lib/rails/commands/rake/rake_command.rb:20:in `perform'
railties/lib/rails/command.rb:48:in `invoke'
railties/lib/rails/commands.rb:18:in `<main>'
```
|
|\ \
| | |
| | | |
Clarify that bulk option is supported only by MySQL
|
| | |
| | |
| | |
| | | |
- Closes #30441
|
| | |
| | |
| | |
| | |
| | |
| | |
| | | |
always true
Because `add_as_polymorphic_through` is only called when
`options[:source_type]` is true.
|
| | |
| | |
| | |
| | | |
`RuntimeReflection#alias_candidate` is no longer used since 0408e212.
|
| | |
| | |
| | | |
Context: https://github.com/rails/rails/pull/29619#discussion_r125158589
|
| | | |
|
|/ /
| |
| |
| |
| |
| | |
I was added a table options after `force: :cascade` in #17569 for not
touching existing tests (reducing diff). But `force: :cascade` is not an
important information. So I prefer to place a table options before
`force: :cascade`.
|
| | |
|
|\ \
| | |
| | | |
Fix broken doc for Active Record [ci skip]
|
| | | |
|
| | | |
|
|/ /
| |
| |
| |
| |
| |
| | |
This regression was caused by caa178c1. The block for
`set_inverse_instance` should also be passed to join dependency.
Fixes #30402.
|
| | |
|
|\ \
| |/
|/| |
Refactor `SchemaDumper` to make it possible to adapter specific customization
|