aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
Commit message (Collapse)AuthorAgeFilesLines
* Namespace association extension modules under the owner modelJean Boussier2019-05-021-2/+2
|
* Make scope arity check consistent (#36134)Rob Trame2019-05-011-1/+1
| | | | | | | | * Make scope arity check consistent * Add test for arity change [Rob Trame + Rafael Mendonça França]
* Should take the record's state of first action in the transactionRyuta Kamizono2019-04-301-8/+9
| | | | | | | | | | | | | | | | If the same id's records are saved and/or destroyed in the transaction, commit callbackes will only run for the first enrolled record. https://github.com/rails/rails/blob/a023e2180093ebc517a642aaf21f3c7241c67657/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L115-L119 The regression #36132 is caused due to #35920 changed the enrollment order that the first action's record will be enrolled to last in the transaction. We could not change the the enrollment order as long as someone depends on the enrollment order. Fixes #36132.
* Fix rubocop offencesRyuta Kamizono2019-04-301-2/+2
|
* Extract `_raise_record_not_touched_error`Ryuta Kamizono2019-04-292-16/+13
|
* Fix merging left_joins to maintain its own `join_type` contextRyuta Kamizono2019-04-274-17/+24
| | | | | | | | | | | | | | | This fixes a regression for #35864. Usually, stashed joins (mainly eager loading) are performed as LEFT JOINs. But the case of merging joins/left_joins of different class, that (stashed) joins are performed as the same `join_type` as the parent context for now. Since #35864, both (joins/left_joins) stashed joins might be contained in `joins_values`, so each stashed joins should maintain its own `join_type` context. Fixes #36103.
* Merge pull request #32313 from lulalala/model_error_as_objectRafael França2019-04-241-16/+9
|\ | | | | Model error as object
| * Allow errors to remove duplicates, and ensure cyclic associations w/ ↵lulalala2019-03-311-3/+1
| | | | | | | | | | autosave duplicate errors can be removed See SHA 7550f0a016ee6647aaa76c0c0ae30bebc3867288
| * Use errors#import instead of manipulating errors/details hashlulalala2019-03-311-13/+8
| |
* | Start Rails 6.1 developmentRafael Mendonça França2019-04-242-3/+6
| |
* | Merge pull request #35869 from ↵Ryuta Kamizono2019-04-251-2/+34
|\ \ | | | | | | | | | | | | | | | abhaynikam/35866-add-touch-option-for-has-one-association Adds missing touch option to has_one association
| * | Adds touch option to has_one associationAbhay Nikam2019-04-251-2/+34
| | |
* | | Avoid redundant `attribute_alias?` before `attribute_alias`Ryuta Kamizono2019-04-247-19/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If we want to get alias resolved attribute finally, we can use `attribute_alias` directly. For that purpose, avoiding redundant `attribute_alias?` makes alias attribute access 40% faster. https://gist.github.com/kamipo/e427f080a27b46f50bc508fae3612a0e Before (2c0729d8): ``` Warming up -------------------------------------- user['id'] 102.668k i/100ms user['new_id'] 80.660k i/100ms user['name'] 99.368k i/100ms user['new_name'] 81.626k i/100ms Calculating ------------------------------------- user['id'] 1.431M (± 4.0%) i/s - 7.187M in 5.031985s user['new_id'] 1.042M (± 4.2%) i/s - 5.243M in 5.039858s user['name'] 1.406M (± 5.6%) i/s - 7.055M in 5.036743s user['new_name'] 1.074M (± 3.6%) i/s - 5.387M in 5.024152s ``` After (this change): ``` Warming up -------------------------------------- user['id'] 109.775k i/100ms user['new_id'] 103.303k i/100ms user['name'] 105.988k i/100ms user['new_name'] 99.618k i/100ms Calculating ------------------------------------- user['id'] 1.520M (± 6.7%) i/s - 7.574M in 5.011496s user['new_id'] 1.485M (± 6.2%) i/s - 7.438M in 5.036252s user['name'] 1.538M (± 5.4%) i/s - 7.737M in 5.049765s user['new_name'] 1.516M (± 4.6%) i/s - 7.571M in 5.007293s ```
* | | Fix sliced IN clauses to be groupedRyuta Kamizono2019-04-244-121/+50
| | | | | | | | | | | | | | | | | | | | | Follow up of #35838. And also this refactors `in_clause_length` handling is entirely integrated in Arel visitor.
* | | Re-organize `init_internals`Ryuta Kamizono2019-04-241-5/+4
| | | | | | | | | | | | | | | * Avoid duplicated `@new_record` assignment * Extract `define_attribute_methods` into `init_internals`
* | | Simplify restore state conditionRyuta Kamizono2019-04-241-4/+2
| | | | | | | | | | | | Follow up to b1458218c95d85c4ce911dd3e99da5ae7cf7aeee.
* | | Lazy allocate `@_start_transaction_state`Ryuta Kamizono2019-04-242-8/+10
|/ /
* | Merge pull request #36070 from imechemi/fix-minor-api-docRyuta Kamizono2019-04-241-1/+1
|\ \ | | | | | | | | | | | | Minor API doc fix [ci skip]
| * | Fix rdoc rendering for push alias symbolTenzin Chemi2019-04-231-1/+1
| | |
* | | Rename local variable `n` to `name`Ryuta Kamizono2019-04-242-3/+3
|/ /
* | Make association builder methods privateRyuta Kamizono2019-04-246-0/+15
| |
* | Merge pull request #36029 from kamipo/deprecate_where_notRyuta Kamizono2019-04-232-9/+26
|\ \ | | | | | | Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1
| * | Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1Ryuta Kamizono2019-04-192-9/+26
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | `where.not` with polymorphic association is partly fixed incidentally at 213796f (refer #33493, #26207, #17010, #16983, #14161), and I've added test case e9ba12f to avoid lose that fix accidentally in the future. In Rails 5.2, `where.not(polymorphic: object)` works as expected as NAND, but `where.not(polymorphic_type: object.class.polymorphic_name, polymorphic_id: object.id)` still unexpectedly works as NOR. To will make `where.not` working desiredly as NAND in Rails 6.1, this deprecates `where.not` working as NOR. If people want to continue NOR conditions, we'd encourage to them to `where.not` each conditions manually. ```ruby all = [treasures(:diamond), treasures(:sapphire), cars(:honda), treasures(:sapphire)] assert_equal all, PriceEstimate.all.map(&:estimate_of) ``` In Rails 6.0: ```ruby sapphire = treasures(:sapphire) nor = all.reject { |e| e.estimate_of_type == sapphire.class.polymorphic_name }.reject { |e| e.estimate_of_id == sapphire.id } assert_equal [cars(:honda)], nor without_sapphire = PriceEstimate.where.not( estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id ) assert_equal nor, without_sapphire.map(&:estimate_of) ``` In Rails 6.1: ```ruby sapphire = treasures(:sapphire) nand = all - [sapphire] assert_equal [treasures(:diamond), cars(:honda)], nand without_sapphire = PriceEstimate.where.not( estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id ) assert_equal nand, without_sapphire.map(&:estimate_of) ``` Resolves #31209.
* | | Avoid new string instance creation in `InsertAll#execute`Ryuta Kamizono2019-04-221-3/+3
| | |
* | | Don't table name qualify aggrigate column for virtual attributeRyuta Kamizono2019-04-221-4/+2
| | | | | | | | | | | | Related 0ee96d13de29680e148ccb8e5b68025f29fd091c.
* | | Merge pull request #36052 from kamipo/fast_idRyuta Kamizono2019-04-228-26/+22
|\ \ \ | | | | | | | | PERF: 20% faster pk attribute access
| * | | PERF: 20% faster pk attribute accessRyuta Kamizono2019-04-228-26/+22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I've realized that `user.id` is 20% slower than `user.name` in the benchmark (https://github.com/rails/rails/pull/35987#issuecomment-483882480). The reason that performance difference is that `self.class.primary_key` method call is a bit slow. Avoiding that method call will make almost attribute access faster and `user.id` will be completely the same performance with `user.name`. Before (02b5b8cb): ``` Warming up -------------------------------------- user.id 140.535k i/100ms user['id'] 96.549k i/100ms user.name 158.110k i/100ms user['name'] 94.507k i/100ms user.changed? 19.003k i/100ms user.saved_changes? 25.404k i/100ms Calculating ------------------------------------- user.id 2.231M (± 0.9%) i/s - 11.243M in 5.040066s user['id'] 1.310M (± 1.3%) i/s - 6.565M in 5.012607s user.name 2.683M (± 1.2%) i/s - 13.439M in 5.009392s user['name'] 1.322M (± 0.9%) i/s - 6.615M in 5.003239s user.changed? 201.999k (±10.9%) i/s - 1.007M in 5.091195s user.saved_changes? 258.214k (±17.1%) i/s - 1.245M in 5.007421s ``` After (this change): ``` Warming up -------------------------------------- user.id 158.364k i/100ms user['id'] 106.412k i/100ms user.name 158.644k i/100ms user['name'] 107.518k i/100ms user.changed? 19.082k i/100ms user.saved_changes? 24.886k i/100ms Calculating ------------------------------------- user.id 2.768M (± 1.1%) i/s - 13.936M in 5.034957s user['id'] 1.507M (± 2.1%) i/s - 7.555M in 5.017211s user.name 2.727M (± 1.5%) i/s - 13.643M in 5.004766s user['name'] 1.521M (± 1.3%) i/s - 7.634M in 5.018321s user.changed? 200.865k (±11.1%) i/s - 992.264k in 5.044868s user.saved_changes? 269.652k (±10.5%) i/s - 1.344M in 5.077972s ```
* | | | Remove useless `set_value` / `get_value` helper methodsRyuta Kamizono2019-04-222-17/+10
|/ / / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Those helper methods makes relation values access 15% slower. https://gist.github.com/kamipo/e64439f7a206e1c5b5c69d92d982828e Before (02b5b8cb): ``` Warming up -------------------------------------- #limit_value 237.074k i/100ms #limit_value = 1 222.052k i/100ms Calculating ------------------------------------- #limit_value 6.477M (± 2.9%) i/s - 32.479M in 5.019475s #limit_value = 1 5.297M (± 4.3%) i/s - 26.424M in 4.999933s ``` After (this change): ``` Warming up -------------------------------------- #limit_value 261.109k i/100ms #limit_value = 1 239.646k i/100ms Calculating ------------------------------------- #limit_value 7.412M (± 1.6%) i/s - 37.077M in 5.003345s #limit_value = 1 6.134M (± 1.0%) i/s - 30.675M in 5.000908s ```
* | | Remove never used `database_selector` class accessorRyuta Kamizono2019-04-221-1/+0
| | | | | | | | | | | | It was never used from the beginning.
* | | Avoid method call if `@transaction_state` is not finalizedRyuta Kamizono2019-04-217-14/+14
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Method call in Ruby is a bit slow. This makes attribute access 10% faster by avoiding method call (`sync_with_transaction_state`). Before (96cf7e0e): ``` Warming up -------------------------------------- user.id 131.291k i/100ms user['id'] 91.786k i/100ms user.name 151.605k i/100ms user['name'] 92.664k i/100ms user.changed? 17.772k i/100ms user.saved_changes? 23.909k i/100ms Calculating ------------------------------------- user.id 1.988M (± 7.0%) i/s - 9.978M in 5.051474s user['id'] 1.155M (± 5.8%) i/s - 5.783M in 5.022672s user.name 2.450M (± 4.3%) i/s - 12.280M in 5.021234s user['name'] 1.263M (± 2.1%) i/s - 6.394M in 5.066638s user.changed? 175.070k (±13.3%) i/s - 853.056k in 5.011555s user.saved_changes? 259.114k (±11.8%) i/s - 1.267M in 5.001260s ``` After (this change): ``` Warming up -------------------------------------- user.id 137.625k i/100ms user['id'] 96.054k i/100ms user.name 156.379k i/100ms user['name'] 94.795k i/100ms user.changed? 18.172k i/100ms user.saved_changes? 24.337k i/100ms Calculating ------------------------------------- user.id 2.201M (± 0.5%) i/s - 11.010M in 5.002955s user['id'] 1.320M (± 1.0%) i/s - 6.628M in 5.021293s user.name 2.677M (± 1.6%) i/s - 13.449M in 5.024399s user['name'] 1.314M (± 1.8%) i/s - 6.636M in 5.051444s user.changed? 190.588k (±11.1%) i/s - 944.944k in 5.065848s user.saved_changes? 262.782k (±12.1%) i/s - 1.290M in 5.028080s ```
* | | Merge pull request #36041 from ↵Ryuta Kamizono2019-04-201-1/+1
|\ \ \ | | | | | | | | | | | | | | | | abhaynikam/change-deprecation-for-dynamic-route-segment-to-6.1 Change the deprecation message for dynamic routes segment to 6.1
| * | | Change deprecation message for dangerous query method to be disallowed in ↵Abhay Nikam2019-04-201-1/+1
| | | | | | | | | | | | | | | | Rails 6.1
* | | | Remove description for namespaced `db:migrate:up`eileencodes2019-04-191-1/+0
|/ / / | | | | | | | | | | | | This was accidentally left in, the standard `db:migrate:up` doesn't have a description so `db:migrate:up:namespace` shouldn't have one either.
* | | Handle up/down for multiple databaseseileencodes2019-04-192-0/+57
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This change adds the ability to run up/down for a database in a multi-db environment. If you have an app with a primary and animals database the following tasks will be generated: ``` VERSION=123 rake db:migrate:up:primary VERSION=123 rake db:migrate:up:primary VERSION=123 rake db:migrate:down:primary VERSION=123 rake db:migrate:up:animals ``` I didn't generate descriptions with them since we don't generate a description for a single database application. In addition to this change I've made it so if your application has multiple databases Rails will raise if you try to run `up` or `down` without a namespace. This is because we don't know which DB you want to run `up` or `down` against unless the app tells us, so it's safer to just block it and recommend using namespaced versions of up/down respectively. The output for the raise looks like: ``` You're using a multiple database application. To use `db:migrate:down` you must run the namespaced task with a VERSION. Available tasks are db:migrate:down:primary and db:migrate:down:animals. ```
* | | Revert "Deprecate `collection_cache_key` which is private API"Ryuta Kamizono2019-04-192-3/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reverts commit f656bb301a43fe441af0039e4fafe40a7faa62f8. Reason: Test in Action View expects the `collection_cache_key` working... https://github.com/rails/rails/blob/ff6b713f5e729859995f204093ad3f8e08f39ea8/actionview/test/activerecord/relation_cache_test.rb#L21 https://github.com/rails/rails/blob/ff6b713f5e729859995f204093ad3f8e08f39ea8/actionview/test/fixtures/project.rb#L6 https://buildkite.com/rails/rails/builds/60609#d19181fb-fe80-4d1e-891c-1109b540fb4b/981-1009
* | | Merge pull request #35998 from itsWill/add_documentation_for_add_indexEileen M. Uchitelle2019-04-191-0/+20
|\ \ \ | | | | | | | | Document algorithm: concurrent option for PostgreSQL [ci skip]
| * | | Document algorithm: concurrent options for PostgreSQL [ci skip]Guilherme Mansur2019-04-161-0/+20
| | | |
* | | | Deprecate `collection_cache_key` which is private APIRyuta Kamizono2019-04-192-2/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The `collection_cache_key` is private API for a long time, but I've maintained it in #35848 since it is mentioned in the doc (https://github.com/rails/rails/pull/35848#discussion_r272011475). The doc has removed at 1da9a7e4, so there is no longer a reason to maintain that private API.
* | | | Merge pull request #34788 from gsamokovarov/actionable-errorsKasper Timm Hansen2019-04-191-0/+7
|\ \ \ \ | | | | | | | | | | Introduce Actionable Errors
| * | | | Make ActiveRecord::PendingMigrationError actionableGenadi Samokovarov2019-04-191-0/+6
| | | | |
| * | | | Introduce Actionable ErrorsGenadi Samokovarov2019-04-191-0/+1
| | |/ / | |/| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Actionable errors let's you dispatch actions from Rails' error pages. This can help you save time if you have a clear action for the resolution of common development errors. The de-facto example are pending migrations. Every time pending migrations are found, a middleware raises an error. With actionable errors, you can run the migrations right from the error page. Other examples include Rails plugins that need to run a rake task to setup themselves. They can now raise actionable errors to run the setup straight from the error pages. Here is how to define an actionable error: ```ruby class PendingMigrationError < MigrationError #:nodoc: include ActiveSupport::ActionableError action "Run pending migrations" do ActiveRecord::Tasks::DatabaseTasks.migrate end end ``` To make an error actionable, include the `ActiveSupport::ActionableError` module and invoke the `action` class macro to define the action. An action needs a name and a procedure to execute. The name is shown as the name of a button on the error pages. Once clicked, it will invoke the given procedure.
* | | | Give GeneratedRelationMethods module a nameRyuta Kamizono2019-04-191-1/+4
| | | | | | | | | | | | | | | | This follows #35595.
* | | | Revert renamed `GeneratedAttributeMethods`Ryuta Kamizono2019-04-191-3/+3
|/ / / | | | | | | | | | | | | | | | | | | This partly reverts 8ca3c286a768038f6b391fd3bfbdfcc299876a1f. `.is_a?(GeneratedAttributeMethodsBuilder)` doesn't make sense to me, the module class's `new` creates just an instance of the module class itself.
* | | Ensure active record can load without Railtieseileencodes2019-04-182-7/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When I added the rake tasks for multiple databases I accidentally made it so you couldn't use Active Record without Railties. Since getting the database configuration depends on being able to load Railties (there is no other way to read and parse the yaml file and load it) I've decided that using multiple databases outside of Rails is a no-op. I've changed the code here to return if Rails isn't defined. Then I changed the other tasks to use `ActiveRecord::Tasks::DatabaseTasks.env` instead of `Rails.env`. The multi-db tasks can keep using `Rails.env` because they'll only be generated if we're using Rails and not just Active Record.
* | | Merge pull request #35987 from kamipo/fix_dirty_tracking_after_rollbackRyuta Kamizono2019-04-177-25/+27
|\ \ \ | | | | | | | | | | | | Fix dirty tracking after rollback.
| * | | Fix dirty tracking after rollback.Ryuta Kamizono2019-04-167-25/+27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Currently the rollback only restores primary key value, `new_record?`, `destroyed?`, and `frozen?`. Since the `save` clears current dirty attribute states, retrying save after rollback will causes no change saved if partial writes is enabled (by default). This makes `remember_transaction_record_state` remembers original values then restores dirty attribute states after rollback. Fixes #15018. Fixes #30167. Fixes #33868. Fixes #33443. Closes #33444. Closes #34504.
* | | | Add collection cache versioningLachlan Sylvester2019-04-162-15/+44
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Cache versioning enables the same cache key to be reused when the object being cached changes by moving the volatile part of the cache key out of the cache key and into a version that is embedded in the cache entry. This is already occurring when the object being cached is an `ActiveRecord::Base`, but when caching an `ActiveRecord::Relation` we are currently still putting the volatile information (max updated at and count) as part of the cache key. This PR moves the volatile part of the relations `cache_key` into the `cache_version` to support recycling cache keys for `ActiveRecord::Relation`s.
* | | | Merge pull request #35946 from alimi/cache-full-mysql-database-versionKasper Timm Hansen2019-04-163-5/+14
|\ \ \ \ | | | | | | | | | | Cache full MySQL version in schema cache
| * | | | Make changes per PR feedbackAli Ibrahim2019-04-122-9/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Remove AbstractMysqlAdapter::Version since full_version_string will always be set. * Remove nodoc on private methods because private methods are not exposed in the docs.
| * | | | Cache full MySQL version in schema cacheAli Ibrahim2019-04-113-6/+21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * The database version is cached in all the adapters, but this didn't include the full MySQL version. Anything that uses the full MySQL version would need to query the database to get that data even if they're using the schema cache. * Now the full MySQL version will be cached in the schema cache via the Version object.