aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases/reflection_test.rb
Commit message (Collapse)AuthorAgeFilesLines
* Cache results of computing model typeKonstantin Lazarev2017-01-031-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | We faced a significant performance decrease when we started using STI without storing full namespaced class name in type column (because of PostgreSQL length limit for ENUM types). We realized that the cause of it is the slow STI model instantiation. Problematic method appears to be `ActiveRecord::Base.compute_type`, which is used to find the right class for STI model on every instantiation. It builds an array of candidate types and then iterates through it calling `safe_constantize` on every type until it finds appropriate constant. So if desired type isn't the first element in this array there will be at least one unsuccessful call to `safe_constantize`, which is very expensive, since it's defined in terms of `begin; rescue; end`. This commit is an attempt to speed up `compute_type` method simply by caching results of previous calls. ```ruby class MyCompany::MyApp::Business::Accounts::Base < ApplicationRecord self.table_name = 'accounts' self.store_full_sti_class = false end class MyCompany::MyApp::Business::Accounts::Free < Base end class MyCompany::MyApp::Business::Accounts::Standard < Base # patch .compute_type there end puts '======================= .compute_type =======================' Benchmark.ips do |x| x.report("original method") do MyCompany::MyApp::Business::Accounts::Free.send :compute_type, 'Free' end x.report("with types cached") do MyCompany::MyApp::Business::Accounts::Standard.send :compute_type, 'Standard' end x.compare! end ``` ``` ======================= .compute_type ======================= with types cached: 1529019.4 i/s original method: 2850.2 i/s - 536.46x slower ``` ```ruby 5_000.times do |i| MyCompany::MyApp::Business::Accounts::Standard.create!(name: "standard_#{i}") end 5_000.times do |i| MyCompany::MyApp::Business::Accounts::Free.create!(name: "free_#{i}") end puts '====================== .limit(100).to_a =======================' Benchmark.ips do |x| x.report("without .compute_type patch") do MyCompany::MyApp::Business::Accounts::Free.limit(100).to_a end x.report("with .compute_type patch") do MyCompany::MyApp::Business::Accounts::Standard.limit(100).to_a end x.compare! end ``` ``` ====================== .limit(100).to_a ======================= with .compute_type patch: 360.5 i/s without .compute_type patch: 24.7 i/s - 14.59x slower ```
* "Use assert_nil if expecting nil. This will fail in minitest 6."Akira Matsuda2016-12-251-2/+2
|
* improve error message when include assertions failMichael Grosser2016-09-161-3/+3
| | | | | | assert [1, 3].includes?(2) fails with unhelpful "Asserting failed" message assert_includes [1, 3], 2 fails with "Expected [1, 3] to include 2" which makes it easier to debug and more obvious what went wrong
* Add three new rubocop rulesRafael Mendonça França2016-08-161-1/+1
| | | | | | | | Style/SpaceBeforeBlockBraces Style/SpaceInsideBlockBraces Style/SpaceInsideHashLiteralBraces Fix all violations in the repository.
* modernizes hash syntax in activerecordXavier Noria2016-08-061-36/+36
|
* applies new string literal convention in activerecord/testXavier Noria2016-08-061-66/+66
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* When verifying size of relation, also verify count is ok.Vipul A M2016-01-251-0/+1
|
* Add missing source_type if provided on hmt which belongs to an sti recordVipul A M2016-01-241-0/+9
| | | | Fixes #23209
* Removed mocha from Active Record Part 1Ronak Jangir2015-08-251-16/+24
|
* Improve test for leaky scope chaineileencodes2015-03-181-1/+7
| | | | | | | | | | | | | | | | This is a better test for 51660f0. It is testing that the SQL is the same before and after the previously leaky scope is called. Before if `hotel.drink_designers` was called first then `hotel.recipes` would incorrectly get the scope applied. We want to be sure that the polymorphic hm:t association is not leaking into or affecting the SQL for the hm:t association on `Hotel`. The reason I couldn't do this before was because there was an issue with the SQL getting cached and wanted to resolve that later and then fix the test to be better. Because of the caching, this test requires that `Hotel.reflect_on_association(:recipes).clear_association_scope_cache` be called after the first call to `hotel.recipes` to clear the assocation scope chain and not interfere with the rest of the test.
* Remove unused variable in activerecord reflection_test.Juanito Fatas2015-03-171-1/+1
|
* Fix leaky chain on polymorphic associationeileencodes2015-03-151-0/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If there was a polymorphic hm:t association with a scope AND second non-scoped hm:t association on a model the polymorphic scope would leak through into the call for the non-polymorhic hm:t association. This would only break if `hotel.drink_designers` was called before `hotel.recipes`. If `hotel.recipes` was called first there would be no problem with the SQL. Before (employable_type should not be here): ``` SELECT COUNT(*) FROM "drink_designers" INNER JOIN "chefs" ON "drink_designers"."id" = "chefs"."employable_id" INNER JOIN "departments" ON "chefs"."department_id" = "departments"."id" WHERE "departments"."hotel_id" = ? AND "chefs"."employable_type" = ? [["hotel_id", 1], ["employable_type", "DrinkDesigner"]] ``` After: ``` SELECT COUNT(*) FROM "recipes" INNER JOIN "chefs" ON "recipes"."chef_id" = "chefs"."id" INNER JOIN "departments" ON "chefs"."department_id" = "departments"."id" WHERE "departments"."hotel_id" = ? [["hotel_id", 1]] ``` From the SQL you can see that `employable_type` was leaking through when calling recipes. The solution is to dup the chain of the polymorphic association so it doesn't get cached. Additionally, this follows `scope_chain` which dup's the `source_reflection`'s `scope_chain`. This required another model/table/relationship because the leak only happens on a hm:t polymorphic that's called before another hm:t on the same model. I am specifically testing the SQL here instead of the number of records becasue the test could pass if there was 1 drink designer recipe for the drink designer chef even though the `employable_type` was leaking through. This needs to specifically check that `employable_type` is not in the SQL statement.
* `type_cast_from_user` -> `cast`Sean Griffin2015-02-171-1/+1
|
* `type_cast_for_database` -> `serialize`Sean Griffin2015-02-171-1/+1
|
* `Type#type_cast_from_database` -> `Type#deserialize`Sean Griffin2015-02-171-1/+1
|
* Remove most type related predicates from `Column`Sean Griffin2015-01-301-8/+5
| | | | | | Remaining are `limit`, `precision`, `scale`, and `type` (the symbol version). These will remain on the column, since they mirror the options to the `column` method in the schema definition DSL
* Return a null column from `column_for_attribute` when no column exists.Rafael Mendonça França2015-01-041-4/+18
| | | | | | | | This reverts commit ae96f229f6501d8635811d6b22d75d43cdb880a4. Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/attribute_methods.rb
* Pass symbol as an argument instead of a blockErik Michaels-Ober2014-11-291-2/+2
|
* Add a test for reflection keys as Strings, fixes #16928Zachary Scott2014-11-231-0/+4
| | | | See also PR: #17610
* Begin refactoring ThroughReflectioneileencodes2014-07-081-34/+30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This allows us to decouple AssociationReflection and ThroughReflection making ThroughReflection it's own Reflection bucket in a way. The benefit of this is to be able to remove checks against the macro's symbol for exmaple `macro == :belongs_to`. Get all tests passing again Some of the methods that used to be inherited from MacroReflection through AssociationReflection were no longer getting passed through. They needed to be duplicated into the ThroughReflection. I will extract these out into a separate class. Refactor shared methods into strategy object Now that we've separated ThroughReflection and AssociationReflection we can combine shared methods into one class to avoid duplication. Break out class for each type of reflection This creates a class for each reflection type (has_many, has_one, belongs_to and habtm). We then can remove the need to set the macro symbol in each initialization. Tests were updated to reflect these changes because creation of these reflections is now different. Remove need for @collection instance var We now define `collection?` as `false` by default and set it to `true` in `has_and_belongs_to_many` and `has_many` reflections. This removes the need for the `@collection` instance variable. Raise exception on unknown macro types We shouldn't accept just any macro when creating reflections. An unrecongnized AssociationReflection raises an error. Tests in `reflection_test` were updated to reflect these new changes. `:has_and_belongs_to_many` macro tests were removed because we no longer internally return HABTM.
* Add regression tests for keys on nested associationseileencodes2014-07-011-0/+32
| | | | | | This adds the regressions tests from issue #15893 to master. It's checking that both strings and symbols are accepted as keys for nested associations.
* Add a deprecation cycle for `NullColumn` from `column_for_attribute`Sean Griffin2014-06-231-18/+4
| | | | | | This is public API, and `simple_form` depends on the `nil` return value. We need to go through a deprecation cycle to return a null object. If people want hash access, they can access the hash.
* Rename `type_cast` to `type_cast_from_database`Sean Griffin2014-06-091-1/+1
| | | | | | | | In some cases there is a difference between the two, we should always be doing one or the other. For convenience, `type_cast` is still a private method on type, so new types that do not need different behavior don't need to implement two methods, but it has been moved to private so it cannot be used accidentally.
* Make `_before_type_cast` actually be before type castSean Griffin2014-06-091-1/+1
| | | | | | | | | | | | | - The following is now true for all types, all the time - `model.attribute_before_type_cast == given_value` - `model.attribute == model.save_and_reload.attribute` - `model.attribute == model.dup.attribute` - `model.attribute == YAML.load(YAML.dump(model)).attribute` - Removes the remaining types implementing `type_cast_for_write` - Simplifies the implementation of time zone aware attributes - Brings tz aware attributes closer to being implemented as an attribute decorator - Adds additional point of control for custom types
* have an actual `NullColumn` object and update docs accordingly.Yves Senn2014-06-041-0/+1
| | | | | | Follow up to #15438 and #15502. /cc @sgrif
* Return a null column when no column exists for an attributeSean Griffin2014-06-031-0/+19
|
* Merge pull request #15210 from arthurnn/fix_hbtm_reflectionArthur Neves2014-05-241-1/+6
| | | | | | | | | Fix habtm reflection Conflicts: activerecord/CHANGELOG.md activerecord/lib/active_record/counter_cache.rb activerecord/lib/active_record/reflection.rb activerecord/test/cases/reflection_test.rb
* Regression test for irregular inflection on has_manyArthur Neves2014-04-181-0/+8
| | | | | | | Also add a Changelog entry [related #9702] [fixes #8928]
* Make sure the reflection test is passing a String to the reflectionLauro Caetano2014-04-091-1/+1
| | | | cache.
* PostgreSQL and SQLite, remove varchar limit. [Vladimir Sazhin & Toms Mikoss ↵Yves Senn2014-04-041-1/+1
| | | | | | | | | | | | | | | | & Yves Senn] There is no reason for the PG adapter to have a default limit of 255 on :string columns. See this snippet from the PG docs: Tip: There is no performance difference among these three types, apart from increased storage space when using the blank-padded type, and a few extra CPU cycles to check the length when storing into a length-constrained column. While character(n) has performance advantages in some other database systems, there is no such advantage in PostgreSQL; in fact character(n) is usually the slowest of the three because of its additional storage costs. In most situations text or character varying should be used instead.
* scope_chain should not be mutated for other reflectionsNeeraj Singh2013-10-141-0/+16
| | | | | | | | | | | Currently `scope_chain` uses same array for building different `scope_chain` for different associations. During processing these arrays are sometimes mutated and because of in-place mutation the changed `scope_chain` impacts other reflections. Fix is to dup the value before adding to the `scope_chain`. Fixes #3882.
* acually get the actual source reflection :cry::gun:Aaron Patterson2013-07-231-2/+3
|
* Removing not useful test related to reflect_on_all_associationsNeeraj Singh2013-07-021-8/+0
| | | | | | | | | | | | | | | | The comment in the test pretty much summarizes the issue. `FIXME these assertions bust a lot` Adding any type of association in class `Firm` will break this test. I removed some deprecated stuff and this test failed. I do not think this test provides any useful value. First of all who counted last that 39 is the right number of associations. Secondly there are a large number of tests which depend on reflection returning right information about associations. Those tests will start failing if there is a bug in the code.
* Fix tests which started to fail due to commit ↵Takehiro Adachi2013-05-181-3/+3
| | | | | | | | 0123c39f41e2062311b2197e6e230ef8ad67e20e Due to commit 0123c39f41e2062311b2197e6e230ef8ad67e20e, column topic.unique_replies_count has been added, and these test started to fail since the tests depends on the topic tables column info.
* remove duplicated require statements in AR test casesYves Senn2012-10-091-1/+0
|
* Revert "Remove :finder_sql, :counter_sql, :insert_sql, :delete_sql."Jon Leighton2012-08-011-2/+2
| | | | | | | | | This reverts commit 3803fcce26b837c0117f7d278b83c366dc4ed370. Conflicts: activerecord/CHANGELOG.md It will be deprecated only in 4.0, and removed properly in 4.1.
* Revert "Removing composed_of from ActiveRecord."Rafael Mendonça França2012-07-271-0/+24
| | | | | | | | | | | This reverts commit 14fc8b34521f8354a17e50cd11fa3f809e423592. Reason: we need to discuss a better path from this removal. Conflicts: activerecord/lib/active_record/reflection.rb activerecord/test/cases/base_test.rb activerecord/test/models/developer.rb
* Remove :finder_sql, :counter_sql, :insert_sql, :delete_sql.Jon Leighton2012-07-201-2/+2
|
* Represent association scope options as AR::Relations insternally.Jon Leighton2012-07-131-19/+23
|
* Allow associations to take a lambda which builds the scopeJon Leighton2012-07-131-22/+22
|
* Add test cases for 46492949b8c09f99db78b9f7a02d039e7bc6a702Andrew White2012-06-231-0/+52
|
* Removing composed_of from ActiveRecord.Steve Klabnik2012-06-181-24/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | This feature adds a lot of complication to ActiveRecord for dubious value. Let's talk about what it does currently: class Customer < ActiveRecord::Base composed_of :balance, :class_name => "Money", :mapping => %w(balance amount) end Instead, you can do something like this: def balance @balance ||= Money.new(value, currency) end def balance=(balance) self[:value] = balance.value self[:currency] = balance.currency @balance = balance end Since that's fairly easy code to write, and doesn't need anything extra from the framework, if you use composed_of today, you'll have to add accessors/mutators like that. Closes #1436 Closes #2084 Closes #3807
* remove calls to find(:first), find(:last) and find(:all)Jon Leighton2012-04-261-1/+1
|
* reflection test fixedgregolsen2012-01-311-2/+2
|
* Deprecate inferred JOINs with includes + SQL snippets.Jon Leighton2012-01-161-2/+2
| | | | | | See the CHANGELOG for details. Fixes #950.
* serialize fails on subclassAlvaro Bautista2011-12-231-5/+5
|
* Fix test as one more has_many addedArun Agrawal2011-11-041-1/+1
|
* Allow the :class_name option for associations to take a symbol.Jon Leighton2011-11-041-1/+5
| | | | | This is to avoid confusing newbies, and to be consistent with the fact that other options like :foreign_key already allow a symbol or a string.
* Fix #3271.Jon Leighton2011-11-031-0/+6
| | | | | | | | Building the conditions of a nested through association could potentially modify the conditions of the through and/or source association. This is a Bad Thing.
* Raise an exception on unknown primary key inside AssociationReflection.Jon Leighton2011-10-051-0/+15
| | | | | An association between two models cannot be made if a relevant key is unknown, so fail fast rather than generating invalid SQL. Fixes #3207.