aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
Commit message (Collapse)AuthorAgeFilesLines
...
* | | Remove useless condition in `reset_association`Ryuta Kamizono2017-09-181-2/+1
| | | | | | | | | | | | `through_scope` is not empty scope if `options[:source_type]` is given.
* | | Fix docs describing rollback [ci skip]dixpac2017-09-171-2/+2
|/ / | | | | | | | | | | | | * `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.
* | Remove unused explicit delegation to `klass` in `relation`Ryuta Kamizono2017-09-142-3/+2
| | | | | | | | | | | | | | 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`.
* | Don't use `collection.table_name` in `collection_cache_key`Ryuta Kamizono2017-09-141-1/+1
| | | | | | | | | | Because `collection.table_name` doesn't respect table alias. Use `collection.arel_attribute` instead.
* | Don't use `quoted_table_name` in `limited_ids_for`Ryuta Kamizono2017-09-142-2/+8
| | | | | | | | | | | | 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.
* | `quoted_table_name` doesn't respect table aliasRyuta Kamizono2017-09-141-1/+1
| | | | | | | | So using `arel_attribute(primary_key).asc` in `batch_order` instead.
* | Make `in_batches` queries to preparableRyuta Kamizono2017-09-141-3/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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]] ```
* | PERF: Incorrect memoization in ↵Guo Xiang Tan2017-09-111-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `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 ```
* | Merge pull request #30524 from tgxworld/recover_plucK_performanceSean Griffin2017-09-071-14/+17
|\ \ | | | | | | PERF: Recover `ActiveRecord::pluck` performance.
| * | PERF: Recover `ActiveRecord::pluck` performance.Guo Xiang Tan2017-09-061-14/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ```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 ```
* | | Remove unnecessary `join_type` in `AssociationScope`Ryuta Kamizono2017-09-081-5/+1
| | | | | | | | | | | | | | | | | | 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.
* | | Remove duplicated `klass` method in `AssociationReflection`Ryuta Kamizono2017-09-081-16/+11
| | | | | | | | | | | | | | | The superclass (`MacroReflection`) already have the same method definition.
* | | Remove unused `primary_key_type` and `quoted_table_name` in `Reflection`Ryuta Kamizono2017-09-081-8/+0
| | | | | | | | | | | | | | | `primary_key_type` is no longer used since #26718. `quoted_table_name` is no longer used since Rails 3.1.
* | | Fix `quote_default_expression` for UUID with array defaultRyuta Kamizono2017-09-081-1/+1
| | | | | | | | | | | | Fixes #30539.
* | | Don't pass `table` to `last_chain_scope` and `next_chain_scope`Ryuta Kamizono2017-09-072-19/+17
| | | | | | | | | | | | | | | | | | 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`.
* | | `RuntimeReflection` is not a subclass of `PolymorphicReflection`Ryuta Kamizono2017-09-071-26/+6
| | | | | | | | | | | | | | | | | | `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.
* | | `has_many :through` with unscope should affect to through scopeRyuta Kamizono2017-09-072-23/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* | | Don't pass unneeded `reflection` to `add_constraints`Ryuta Kamizono2017-09-051-3/+3
| | | | | | | | | | | | Because `refl.scope` is the same meaning with `chain_head.scope`.
* | | Assigning `values` is only necessary when `reflection_scope.where_clause` is ↵Ryuta Kamizono2017-09-051-1/+1
| | | | | | | | | | | | | | | | | | not empty Because `reflection_scope.values` will create extra new hash.
* | | Don't merge `reflection_scope` if `reflection.scope` isn't givenRyuta Kamizono2017-09-051-1/+1
| | | | | | | | | | | | | | | If `reflection.scope` isn't given, `reflection_scope` is always `klass.unscoped`. it is unnecessary to merge it.
* | | Should quote composite primary key namesRyuta Kamizono2017-09-041-1/+1
|/ / | | | | | | | | | | | | Otherwise using reserved words as composite primary key names will be failed as an invalid SQL. Fixes #30518.
* | Scope in associations should treat nil as `all`Ryuta Kamizono2017-09-045-8/+10
| | | | | | | | | | | | | | | | 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.
* | Fix preloading through association with custom scopeRyuta Kamizono2017-09-021-1/+6
| | | | | | | | | | | | | | | | | | | | 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.
* | `values[:includes]` in `reflection_scope` is not compatible with `through_scope`Ryuta Kamizono2017-09-021-1/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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? ```
* | Don't call `scope.eager_loading?` when `reflection_scope.where_clause` is emptyRyuta Kamizono2017-09-021-10/+10
| | | | | | | | | | If `reflection_scope.where_clause` is empty, `scope` isn't changed. So `scope.eager_loading?` is always false.
* | `add_reference` should respect column position for both reference id and ↵Ryuta Kamizono2017-09-011-1/+1
| | | | | | | | | | | | type columns Fixes #30496.
* | Clarify intentions around method redefinitionsMatthew Draper2017-09-011-3/+2
| | | | | | | | | | | | | | | | | | 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.
* | Merge pull request #30377 from keepcosmos/delegate-missing-methodsMatthew Draper2017-08-311-2/+2
|\ \ | | | | | | Delegate :rindex, :slice, :rotate(missing) to 'records'
| * | Delegate :rindex, :slice, :rotate to 'records'keepcosmos2017-08-241-2/+2
| | |
* | | Fix `can't modify frozen String` error in `DatabaseTasks`yuuji.yaginuma2017-08-302-2/+2
| |/ |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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>' ```
* | Merge pull request #30445 from prathamesh-sonpatki/fix-30441Kasper Timm Hansen2017-08-281-0/+2
|\ \ | | | | | | Clarify that bulk option is supported only by MySQL
| * | Clarify that bulk option is supported only by MySQL [ci skip]Prathamesh Sonpatki2017-08-291-0/+2
| | | | | | | | | | | | - Closes #30441
* | | `@previous_reflection.options[:source_type]` in `PolymorphicReflection` is ↵Ryuta Kamizono2017-08-281-10/+2
| | | | | | | | | | | | | | | | | | | | | always true Because `add_as_polymorphic_through` is only called when `options[:source_type]` is true.
* | | Remove unused `RuntimeReflection#alias_candidate`Ryuta Kamizono2017-08-281-4/+0
| | | | | | | | | | | | `RuntimeReflection#alias_candidate` is no longer used since 0408e212.
* | | Should be appear deprecation message for every call (#29649)Ryuta Kamizono2017-08-271-8/+0
| | | | | | | | | Context: https://github.com/rails/rails/pull/29619#discussion_r125158589
* | | Omit the default limit for float columns (#28041)Ryuta Kamizono2017-08-271-1/+1
| | |
* | | Prefer to place a table options before `force: :cascade` (#28005)Ryuta Kamizono2017-08-271-2/+1
|/ / | | | | | | | | | | 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`.
* | Use tt in doc for ActiveRecord [ci skip]Yoshiyuki Hirano2017-08-276-20/+20
| |
* | Merge pull request #30403 from yhirano55/fix_broken_doc_for_active_recordRyuta Kamizono2017-08-267-7/+7
|\ \ | | | | | | Fix broken doc for Active Record [ci skip]
| * | Fix broken doc for Active Record [ci skip]Yoshiyuki Hirano2017-08-257-7/+7
| | |
* | | Add :nodoc: for ActiveRecord::AttributeMethods [ci skip]Yoshiyuki Hirano2017-08-263-3/+3
| | |
* | | Should work inverse association when eager loadingRyuta Kamizono2017-08-253-15/+18
|/ / | | | | | | | | | | | | This regression was caused by caa178c1. The block for `set_inverse_instance` should also be passed to join dependency. Fixes #30402.
* | Remove unused returning value `stream`Ryuta Kamizono2017-08-241-2/+0
| |
* | Merge pull request #30337 from kamipo/refactor_schema_dumperRyuta Kamizono2017-08-2413-52/+50
|\ \ | |/ |/| Refactor `SchemaDumper` to make it possible to adapter specific customization
| * Refactor `SchemaDumper` to make it possible to adapter specific customizationRyuta Kamizono2017-08-2213-38/+51
| | | | | | | | | | | | | | Currently `SchemaDumper` is only customizable for column options. But 3rd party connection adapters (oracle-enhanced etc) need to customizable for table or index dumping also. To make it possible, I introduced adapter specific `SchemaDumper` classes for that.
| * Remove deprecated `#migration_keys`Ryuta Kamizono2017-08-223-15/+0
| |
* | Merge pull request #30360 from gcourtemanche/transaction_timedoutRafael França2017-08-222-0/+8
|\ \ | |/ |/| Add TransactionTimeout for MySQL error code 1205
| * Add TransactionTimeout for MySQL error code 1205Gabriel Courtemanche2017-08-222-0/+8
| |
* | Automatically guess the inverse associations for STIyui-knk2017-08-221-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ActiveRecord associations automatically guess the inverse associations. But this feature does not work correctly on assoctions for STI. For example, before this commit ``` class Post < ActiveRecord::Base belongs_to :author end class SpecialPost < Post; end class Author < ActiveRecord::Base has_many :posts has_many :special_posts end ``` `author.posts.first.author` works correctly, but `author.special_posts.first.author` does not work correctly.
* | Update links to use https instead of http [ci skip]Yoshiyuki Hirano2017-08-2211-12/+12
|/