aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/models
Commit message (Collapse)AuthorAgeFilesLines
* Merge pull request #33378 from numbata/subclass-redefine-autosave-callbacksRafael Mendonça França2018-09-131-0/+6
|\ | | | | | | Allow subclasses to redefine autosave callbacks for associated records
| * Allow subclasses to redefine autosave callbacks for associated recordsAndrey Subbota2018-07-271-0/+6
| |
* | Eager loading/preloading should be worked regardless of large number of recordsRyuta Kamizono2018-09-121-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since 213796f, bind params are used for IN clause if enabled prepared statements. Unfortunately, most adapter modules have a limitation for # of bind params (mysql2 65535, pg 65535, sqlite3 250000). So if eager loading large number of records at once, that query couldn't be sent to the database. Since eager loading/preloading queries are auto-generated by Active Record itself, so it should be worked regardless of large number of records like as before. Fixes #33702.
* | Fix regression setting children record in parent before_save callback.Guo Xiang Tan2018-09-032-0/+12
| |
* | Permit list usage cleanup and clearer documentationKevin Deisz2018-08-271-1/+1
| |
* | Convert over the rest of the whitelist referencesKevin Deisz2018-08-241-1/+1
| |
* | Fix numericality validator not to be affected by custom getterRyuta Kamizono2018-08-131-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since fe9547b6, numericality validator would parse raw value only when a value came from user to work type casting to a value from database. But that was caused a regression that the validator would work against getter value instead of parsed raw value, a getter is sometimes customized by people. #33550 There we never guarantees that the value before type cast was going to the used in this validation (actually here is only place that getter value might not be used), but we should not change the behavior unless there is some particular reason. The purpose of fe9547b6 is to work type casting to a value from database. We could achieve the purpose by using `read_attribute`, without using getter value. Fixes #33550.
* | Call build when extend with nested attributes definedAlireza Bashiri2018-08-021-1/+7
|/ | | | | | | | What? From now on when `accepts_nested_attributes_for` defined and `extend` option added the overwritten `build` method being called. [Alireza Bashiri, Martins Polakovs]
* Avoid extra scoping in delegating to klass methods in the `scope` blockRyuta Kamizono2018-07-191-0/+1
| | | | | | | | | | Since #29301, delegating to klass methods in the `scope` block would cause extra scoping by the receiver itself. The extra scoping would always override intermediate scoping like `unscoped` and caused the regression #33387. To keep the original scoping behavior, should avoid the extra scoping in the `scope` block. Fixes #33387.
* Ensure to calculate column aliases after all table aliases are constructedRyuta Kamizono2018-06-191-3/+4
| | | | | | | | | | | | | | | | | Currently, column aliases which is used for eager loading are calculated before constructing all table aliases in FROM clause. `JoinDependency#join_constraints` constructs table aliases for `joins` first, and then always re-constructs table aliases for eager loading. If both `joins` and eager loading are given a same table association, the re-construction would cause the discrepancy between column aliases and table aliases. To avoid the discrepancy, the column aliases should be calculated after all table aliases are constructed. Fixes #30603.
* Fix `touch` option to behave consistently with `Persistence#touch` methodRyuta Kamizono2018-06-182-1/+3
| | | | | | | | | | | | | | | | `touch` option was added to `increment!` (#27660) and `update_counters` (#26995). But that option behaves inconsistently with `Persistence#touch` method. If `touch` option is passed attribute names, it won't update update_at/on attributes unlike `Persistence#touch` method. Due to changed from `Persistence#touch` to `increment!` with `touch` option, #31405 has a regression that `counter_cache` with `touch` option which is passed attribute names won't update update_at/on attributes. I think that the inconsistency is not intended. To get back consistency, ensure that `touch` option updates update_at/on attributes.
* Merge pull request #29373 from untidy-hair/store_accessor_enhanceRyuta Kamizono2018-06-131-0/+3
|\ | | | | | | Allow prefix/suffix options for store accessors
| * Update prefix and allow suffix options for store accessorsYukio Mizuta2018-06-121-0/+3
| |
* | Fix `collection.create` to could be rolled back by `after_save`Ryuta Kamizono2018-06-071-0/+10
| | | | | | | | | | | | | | | | | | | | | | In `_create_record`, explicit `transaction` block requires rollback handling manually when `insert_record` is failed. We need to handle it in `_create_record`, not in `insert_record`, since our test cases expect a record added to target and returned even if `insert_record` is failed, Closes #31488.
* | Reuse existing model for testing duplicated children recordsRyuta Kamizono2018-06-072-5/+1
| | | | | | | | Follow up of #32952.
* | Merge pull request #32952 from mechanicles/32940-fixRyuta Kamizono2018-05-292-0/+6
|\ \ | | | | | | | | | Fix parent record should not get saved with duplicate children records
| * | Fix parent record should not get saved with duplicate children recordsSantosh Wadghule2018-05-282-0/+6
| |/ | | | | | | - Fixes #32940
* | Fix that association's after_touch is not called with counter cacheRyuta Kamizono2018-05-271-0/+10
| | | | | | | | | | | | | | | | | | | | | | | | Since #31405, using `#increment!` with touch option instead of `#touch` to touch belongs_to association if counter cache is enabled. It caused the regression since `#increment!` won't invoke after_touch callbacks even if touch option is given. To fix the regression, make `#increment!` invokes after_touch callbacks if touch option is given. Fixes #31559. Fixes #32408.
* | Fix inconsistent touching behavior between assigning and unassigningRyuta Kamizono2018-05-271-1/+1
|/ | | | | | | | | | | On belongs_to with `touch: true` association, unassigned object is caused touching, but assigned object is not touched. And also, if primary key is customized, it will touch against the wrong target looked up by the customized key as primary key. This change ensures correctly touching consistently between assigning and unassigning.
* Rollback parent transaction when children fails to update (#32796)Guillaume Malette2018-05-221-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | * Rollback parent transaction when children fails to update Rails supports autosave associations on the owner of a `has_many` relationship. In certain situation, if the children of the association fail to save, the parent is not rolled back. ```ruby class Employee < ActiveRecord::Base end class Company < ActiveRecord::Base has_many(:employees) end company = Company.new employee = company.employees.new company.save ``` In the previous example, if the Employee failed to save, the Company will not be rolled back. It will remain in the database with no associated Employee. I expect the `company.save` call to be atomic, and either create all or none of the records. The persistance of the Company already starts a transaction that nests it's children. However, it didn't track the success or failure of it's children in this very situation, and the outermost transaction is not rolled back. This PR makes the change to track the success of the child insertion and rollback the parent if any of the children fail. * Change the test to reflect what we expect Once #32862 is merged, rolling back a record will rollback it's state to match the state before the database changes were applied * Use only the public API to express the tests * Refactor to avoid reassigning saved for nested reflections [Guillaume Malette + Rafael Mendonça França]
* `becomes` should clear the mutation tracker which is created in ↵Ryuta Kamizono2018-05-111-1/+1
| | | | | | | | | | | | | | | | `after_initialize` `becomes` creates new object and copies attributes from the receiver. If new object has mutation tracker which is created in `after_initialize`, it should be cleared since it is for discarded attributes. But if the receiver doesn't have mutation tracker yet, it will not be cleared properly. It should be cleared regardless of whether the receiver has mutation tracker or not. Fixes #32867.
* `get_value` needs to be a public methodGraham Turner2018-04-251-0/+3
| | | | | | Adds test case for failing issue Moves set_value back to protected
* Using existing models for building multiple has_one through testsRyuta Kamizono2018-04-225-24/+1
| | | | Follow up of #32514.
* Fix .new with multiple through associationsSam DeCesare2018-04-094-0/+24
| | | | | | | | | | | | | | | | | | | This fixes a bug with building an object that has multiple `has_many :through` associations through the same object. Previously, when building the object via .new, the intermediate object would be created instead of just being built. Here's an example: Given a GameBoard, that has_one Owner and Collection through Game. The following line would cause a game object to be created in the database. GameBoard.new(owner: some_owner, collection: some_collection) Whereas, if passing only one of those associations into `.new` would cause the Game object to be built and not created in the database. Now the above code will only build the Game object, and not save it.
* Merge pull request #32355 from kamipo/delegate_to_klass_in_a_scopeRafael França2018-04-061-0/+8
|\ | | | | Bring back private class methods accessibility in named scope
| * Deprecate accessibility of private/protected class methods in named scopeRyuta Kamizono2018-03-301-2/+3
| |
| * Bring back private class methods accessibility in named scopeRyuta Kamizono2018-03-271-1/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The receiver in a scope was changed from `klass` to `relation` itself for all scopes (named scope, default_scope, and association scope) behaves consistently. In addition. Before 5.2, if both an AR model class and a Relation instance have same named methods (e.g. `arel_attribute`, `predicate_builder`, etc), named scope doesn't respect relation instance information. For example: ```ruby class Post < ActiveRecord::Base has_many :comments1, class_name: "RecentComment1" has_many :comments2, class_name: "RecentComment2" end class RecentComment1 < ActiveRecord::Base self.table_name = "comments" default_scope { where(arel_attribute(:created_at).gteq(2.weeks.ago)) } end class RecentComment2 < ActiveRecord::Base self.table_name = "comments" default_scope { recent_updated } scope :recent_updated, -> { where(arel_attribute(:updated_at).gteq(2.weeks.ago)) } end ``` If eager loading `Post.eager_load(:comments1, :comments2).to_a`, `:comments1` (default_scope) respects aliased table name, but `:comments2` (using named scope) may not work correctly since named scope doesn't respect relation instance information. See also 801ccab. But this is a breaking change between releases without deprecation. I decided to bring back private class methods accessibility in named scope. Fixes #31740. Fixes #32331.
* | Merge pull request #30956 from CJStadler/with-lock-changed-deprecationRafael França2018-03-281-0/+8
|/ | | | Fix deprecation warnings from with_lock
* Add custom prefix to ActiveRecord::Store accessorsTan Huynh2018-03-231-0/+3
| | | | | | Add a prefix option to ActiveRecord::Store.store_accessor and ActiveRecord::Store.store. This option allows stores to have identical keys with different accessors.
* Make `reflection.klass` raise if `polymorphic?` not to be misusedRyuta Kamizono2018-02-193-0/+5
| | | | | | | | | | | | | | | | This is an alternative of #31877 to fix #31876 caused by #28808. This issue was caused by a combination of several loose implementation. * finding automatic inverse association of polymorphic without context (caused by #28808) * returning `klass` even if `polymorphic?` (exists before #28808) * loose verification by `valid_inverse_reflection?` (exists before #28808) This makes `klass` raise if `polymorphic?` not to be misused. This issue will not happen unless polymorphic `klass` is misused. Fixes #31876. Closes #31877.
* Association scope's own order should be prioritized over through scope's orderRyuta Kamizono2018-02-181-1/+2
| | | | | | | | | | 3acc5d6 was changed the order of scope evaluation from through scope to the association's own scope to be prioritized over the through scope. But the sorting order will be prioritized that is evaluated first. It is unintentional effect, association scope's sorting order should be prioritized as well. Fixes #32008.
* Deprecate update_attributes and update_attributes!Eddie Lebow2018-02-171-2/+2
| | | | Closes #31998
* Remove unused/missing `to_money` converter in the test/docRyuta Kamizono2018-01-291-1/+1
|
* Avoid passing unnecessary arguments to relationDaniel Colson2018-01-241-0/+8
| | | | | | | | | | | | Most of the time the table and predicate_builder passed to Relation.new are exactly the arel_table and predicate builder of the given klass. This uses klass.arel_table and klass.predicate_builder as the defaults, so we don't have to pass them in most cases. This does change the signaure of both Relation and AssocationRelation. Are we ok with that?
* Don't update counter cache when through record was not destroyedEugene Kenny2018-01-142-0/+7
| | | | | | When removing a record from a has many through association, the counter cache was being updated even if the through record halted the callback chain and prevented itself from being destroyed.
* Merge pull request #23146 from piotrj/issue_18424Ryuta Kamizono2018-01-111-0/+3
|\ | | | | | | When deleting through records, take into account association conditions
| * When deleting through records, take into account association conditionsPiotr Jakubowski2016-05-041-0/+3
| | | | | | | | | | | | | | | | Fixes #18424. When deleting through records, it didn't take into account the conditions that may have been affecting join model table, but was defined in association definition.
* | Fix newly added reflection order when redefining associationRyuta Kamizono2018-01-041-2/+2
| | | | | | | | | | | | | | | | | | | | Currently reflections keeps the order when first added even if when redefining association. As a result of the order, redefining through association which use newly added association will raise `HasManyThroughOrderError`. We need to redefine reflection order as well when redefining association. Fixes #31068.
* | Merge pull request #27561 from fishbrain/count-all-in-has-many-associationRyuta Kamizono2018-01-031-0/+2
|\ \ | | | | | | | | | Use `count(:all)` in HasManyAssociation#count_records
| * | Use `count(:all)` in HasManyAssociation#count_recordsKlas Eskilson2017-02-071-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Problem: Calling `count` on an association can cause invalid SQL queries to be created where the `SELECT COUNT(a, b, c)` function receives multiple columns. This will cause a `StatementInvalid` exception later on. Solution: Use `count(:all)`, which generates a `SELECT COUNT(*)...` query independently of the association. This also includes a test case that, before the fix, broke.
* | | Add test case for `collection_singular_ids` with symbol primary keysRyuta Kamizono2018-01-011-1/+1
| | | | | | | | | | | | This is a regression test for #27864.
* | | save attributes changed by callbacks after update_attributeMike Busch2017-12-221-0/+7
| | | | | | | | | | | | | | | | | | | | | | | | update_attribute previously stopped execution, before saving and before running callbacks, if the record's attributes hadn't changed. [The documentation](http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_attribute) says that "Callbacks are invoked", which was not happening if the persisted attributes hadn't changed.
* | | Fix conflicts `counter_cache` with `touch: true` by optimistic locking.bogdanvlviv2017-12-121-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ``` # create_table :posts do |t| # t.integer :comments_count, default: 0 # t.integer :lock_version # t.timestamps # end class Post < ApplicationRecord end # create_table :comments do |t| # t.belongs_to :post # end class Comment < ApplicationRecord belongs_to :post, touch: true, counter_cache: true end ``` Before: ``` post = Post.create! # => begin transaction INSERT INTO "posts" ("created_at", "updated_at", "lock_version") VALUES ("2017-12-11 21:27:11.387397", "2017-12-11 21:27:11.387397", 0) commit transaction comment = Comment.create!(post: post) # => begin transaction INSERT INTO "comments" ("post_id") VALUES (1) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1, "lock_version" = COALESCE("lock_version", 0) + 1 WHERE "posts"."id" = 1 UPDATE "posts" SET "updated_at" = '2017-12-11 21:27:11.398330', "lock_version" = 1 WHERE "posts"."id" = 1 AND "posts"."lock_version" = 0 rollback transaction # => ActiveRecord::StaleObjectError: Attempted to touch a stale object: Post. Comment.take.destroy! # => begin transaction DELETE FROM "comments" WHERE "comments"."id" = 1 UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) - 1, "lock_version" = COALESCE("lock_version", 0) + 1 WHERE "posts"."id" = 1 UPDATE "posts" SET "updated_at" = '2017-12-11 21:42:47.785901', "lock_version" = 1 WHERE "posts"."id" = 1 AND "posts"."lock_version" = 0 rollback transaction # => ActiveRecord::StaleObjectError: Attempted to touch a stale object: Post. ``` After: ``` post = Post.create! # => begin transaction INSERT INTO "posts" ("created_at", "updated_at", "lock_version") VALUES ("2017-12-11 21:27:11.387397", "2017-12-11 21:27:11.387397", 0) commit transaction comment = Comment.create!(post: post) # => begin transaction INSERT INTO "comments" ("post_id") VALUES (1) UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) + 1, "lock_version" = COALESCE("lock_version", 0) + 1, "updated_at" = '2017-12-11 21:37:09.802642' WHERE "posts"."id" = 1 commit transaction comment.destroy! # => begin transaction DELETE FROM "comments" WHERE "comments"."id" = 1 UPDATE "posts" SET "comments_count" = COALESCE("comments_count", 0) - 1, "lock_version" = COALESCE("lock_version", 0) + 1, "updated_at" = '2017-12-11 21:39:02.685520' WHERE "posts"."id" = 1 commit transaction ``` Fixes #31199.
* | | Inverse instance should not be reloaded during autosave if called in validationAnmol Chopra2017-11-271-0/+4
| | | | | | | | | | | | | | | Record saved in save_has_one_association already make call to association.loaded! via record's before_save callback of save_belongs_to_association, but this will reload object if accessed in record's validation.
* | | try using regexesBen Toews2017-11-097-21/+17
| | |
* | | allow table name and direction in string order argBen Toews2017-11-099-25/+29
| | |
* | | work around deprecation warnings in a bunch of testsBen Toews2017-11-0914-42/+46
| | |
* | | `scoping` should respect current class and STI constraint (#29199)Ryuta Kamizono2017-11-061-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | A relation includes `klass`, so it can not be used as it is if current class is different from `current_scope.klass`. It should be created new relation by current class to respect the klass and STI constraint. Fixes #17603. Fixes #23576.
* | | delegate scope forpavel2017-10-274-0/+5
| | |
* | | Place `MocktailDesigner` in `test/models/drink_designer.rb`Ryuta Kamizono2017-10-232-4/+3
| | | | | | | | | | | | | | | Since `MocktailDesigner` inherits `DrinkDesigner` and can not be used alone.