aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/reflection.rb
Commit message (Collapse)AuthorAgeFilesLines
* start hiding the `scope_chain` data structureAaron Patterson2016-03-041-0/+10
| | | | | Introduce a predicate method that doesn't need to build a scope chain, but also hides the data structure used for representing the scope chain.
* don't build the reflection chain to calculate `nested?`Aaron Patterson2016-03-041-1/+9
| | | | | | | | We know a reflection can be considered as `nested?` if the source reflection or the through reflection are also through reflections (since the through reflection will also add another join table). This allows us to avoid traversing the entire reflection tree just to calculate whether or not there will be more join tables.
* remove useless ivarAaron Patterson2016-03-041-1/+0
|
* Respect through association scopes when used with polymorphicSean Griffin2016-02-291-1/+1
| | | | | | | | | | | When the `source_type` option is passed to a has_many through, the resulting `Reflection` will be an instance of `PolymorphicReflection` and not `ThroughReflection`, meaning that it will ignore the scopes that it needs to apply from the through reflections. This adds an additional delegation call to remedy this. I've been finding the reflection code completely impenetrable lately, it could use some major love. Fixes #22726
* build scope chain functionally and remove cachingAaron Patterson2016-02-101-14/+40
| | | | | | | This commit walks the reflection tree and builds the scope chain functionally. It also removes the chain cache since the cache doesn't seem to have any impact on performance (I'd prefer to only cache at proven bottlenecks)
* Merge branch 'master' of github.com:rails/docrailsVijay Dev2016-02-071-10/+13
|\
| * fix indentationVijay Dev2016-02-071-1/+1
| |
| * [ci skip] Update internal documents about ActiveRecord's Reflectionyui-knk2016-01-301-11/+14
| | | | | | | | | | | | | | ActiveRecord's Reflection was refactored by f8d2899d12d59360f29c5eb6a1b1a8fe4ec82ca0 . Top of ancestors chain was changed to `AbstractReflection` from `MacroReflection`, and new Reflections were added.
* | Remove unnecessary overriding of `#initialize`yui-knk2016-02-021-12/+0
| | | | | | | | | | | | `#initialize` of `HasManyReflection`, `HasOneReflection` and `BelongsToReflection` only pass all arguments to `super` by passed order. These overriding can be removed.
* | Remove `case macro` from `calculate_constructable`yui-knk2016-02-011-8/+13
| | | | | | | | | | | | | | | | | | Rails has abstract Reflection classes (`MacroReflection`, `AssociationReflection` etc.) and concrete Reflection classes (e.g. `HasManyReflection`, `HasOneReflection` etc.). In many case `calculate_constructable` returns `true`, so change `calculate_constructable` to always return `true` and override this method if necessary.
* | Each concrete classes have responsibility to return `association_class`yui-knk2016-01-311-22/+25
| |
* | Merge branch '5-0-beta-sec'Aaron Patterson2016-01-251-2/+2
|\ \ | |/ |/| | | | | | | | | | | | | | | | | * 5-0-beta-sec: bumping version fix version update task to deal with .beta1.1 Eliminate instance level writers for class accessors allow :file to be outside rails root, but anything else must be inside the rails view directory Don't short-circuit reject_if proc stop caching mime types globally use secure string comparisons for basic auth username / password
| * Eliminate instance level writers for class accessorsAaron Patterson2016-01-221-2/+2
| | | | | | | | | | | | | | | | | | Instance level writers can have an impact on how the Active Model / Record objects are saved. Specifically, they can be used to bypass validations. This is a problem if mass assignment protection is disabled and specific attributes are passed to the constructor. CVE-2016-0753
* | [ci skip] `automatic_inverse_of` returns `false` not `nil` (document fix)yui-knk2016-01-091-1/+1
|/
* Freeze association foreign keys to reduce allocationsSean Griffin2015-11-151-1/+1
| | | | | | | | | | | | The string returned here will ultimately get used as a key of a hash in the attribute set once the attributes are being built. When you give a non-frozen string to `Hash#[]`, it will be duped. Be freezing we can significantly reduce the number of times we end up allocating `"user_id"` This does not include any additional tests, as this should not have any public facing implications. If you are mutating the result of `Reflection#foreign_key`, please stop.
* Wrong usage of 'a' in docs fixed [ci skip]Mehmet Emin İNAÇ2015-10-031-1/+1
|
* Fix regression in inverse_of on through associationseileencodes2015-09-261-14/+16
| | | | | | | | | | | | | | | | | | | `inverse_of` on through associations was accidently removed/caused to stop working in commit f8d2899 which was part of a refactoring on `ThroughReflection`. To fix we moved `inverse_of` and `check_validity_of_inverse!` to the `AbstractReflection` so it's available to the `ThroughReflection` without having to dup any methods. We then need to delegate `inverse_name` method in `ThroughReflection`. `inverse_name` can't be moved to `AbstractReflection` without moving methods that set the instance variable `@automatic_inverse_of`. This adds a test that ensures that `inverse_of` on a `ThroughReflection` returns the correct class name, and the correct record for the inverse relationship. Fixes #21692
* [ci skip] Remove useless "@api public/private"yui-knk2015-09-171-7/+1
| | | | Other public APIs do not have these annotations.
* Merge pull request #21486 from bogdan/refactor-has-many-counter-cacheEileen M. Uchitelle2015-09-091-9/+50
|\ | | | | HasManyAssociation: moved half of counter cache code to reflection
| * HasManyAssociation: moved half of counter cache code to reflectionBogdan Gusiev2015-09-031-9/+50
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Current implementation has a lot of utility methods that accept reflection call a lot of methods on it and exit. E.g. has_counter_cache?(reflection) It causes confusion and inability to cache result of the method even through it always returns the same result for the same reflection object. It can be done easier without access to the association context by moving code into reflection itself. e.g. reflection.has_counter_cache? Reflection is less complex object than association so moving code there automatically makes it simplier to understand.
* | :bomb:Rafael Mendonça França2015-09-081-1/+1
| |
* | Memoized reflections accessorRafael Mendonça França2015-09-081-9/+18
|/ | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Its value never change since associations are defined at class load time so there is no need to build the hash everytime the method is called. Before this change: Calculating ------------------------------------- reflections 804.000 i/100ms ------------------------------------------------- reflections 8.213k (±26.2%) i/s - 36.180k After this change: Calculating ------------------------------------- reflections 24.548k i/100ms ------------------------------------------------- reflections 1.591M (±25.7%) i/s - 7.364M Benchmark script: require 'bundler/setup' require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do 100.times do |i| create_table "users#{i}", force: true end create_table :cars, force: true do |t| 100.times do |i| t.references "users#{i}" end end end class Car < ActiveRecord::Base 100.times do |i| belongs_to "users#{i}".to_sym end end Benchmark.ips do |x| x.report('reflections') { Car.reflections } end
* parent_reflection should store only a reflection objectAaron Patterson2015-05-191-5/+7
| | | | | we should ask the reflection for its name rather than storing the reflection name in two places (an array and a reflection object)
* Rename association option :class to :anonymous_classAndrew White2015-04-211-2/+2
| | | | | | | | | | | | | In 1f006c an option was added called :class to allow passing anonymous classes to association definitions. Since using :class instead of :class_name is a fairly common typo even amongst experienced developers this can result in hard to debug errors arising in raise_on_type_mismatch? To fix this we're renaming the option from :class to :anonymous_class as that is a more correct description of what the option is for. Since this was an internal, undocumented option there is no need for a deprecation. Fixes #19659
* Add `clear_association_scope_cache` methodeileencodes2015-03-181-0/+15
| | | | | | | | | | | | | In the tests if I were to call `post.categorizations.to_a` and then later call `post.categorizations.to_a` expecting to have different results the 2 queries would be the same because of the caching involved in `@association_scope_cache`. The chain gets cached and the queries will be the same even if they are not supposed to be (i.e. testing an order dependent scoping issue). I found this issue because I was working on a bug with cached scoped in hm:t and hm:t polymorphic relationships but `capture_sql` was outputting the wrong SQL to write a good test.
* reflection doc fix about hierarchykeepcosmos2015-03-171-1/+1
|
* Fix leaky chain on polymorphic associationeileencodes2015-03-151-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* remove deprecated support to preload instance-dependent associaitons.Yves Senn2015-01-051-6/+3
| | | | Addresses https://github.com/rails/rails/commit/ed56e596a0467390011bc9d56d462539776adac1#commitcomment-9145960
* Remove deprecated `Reflection#source_macro`Rafael Mendonça França2015-01-041-19/+0
|
* Cleanup methods, missing spacing and missing nodocseileencodes2015-01-021-14/+14
| | | | | | | | | | Add missing nodoc's Change `assoc_klass` argument name to `association_klass` Change `prev_reflection` argument name to `previous_reflection` Change `prev` to `previous_reflection` in `#get_chain` Switch use of `refl` and `reflection` in `#get_chain` so main parameter is not abbreviated. Add missing space in `#add_constraints`
* Add `#all_includes` method to reflectionseileencodes2015-01-021-0/+2
| | | | | `yield` instead of relying on checking if the reflection is equal to the `chain_head`.
* Move `alias_candiate` into `AbstractReflection`eileencodes2015-01-021-1/+9
| | | | | | This moves `alias_candidate` out of the `ReflectionProxy` and into the `AbstractReflection` so it is shared by all reflections. Change `alias_name` to a method and and remove assignment in `#get_chain`.
* Assign the `#alias_name` to each reflectioneileencodes2015-01-021-7/+3
| | | | This makes the `#alias_name` more functional.
* Clean up / refactor new reflection classeseileencodes2015-01-021-42/+75
| | | | | | Move `RuntimeReflection` and `PolymorphicReflect` into Reflection. This allows the methods to inherit from `ThroughReflection` and DRY up the methods by removing duplicates.
* Move `#alias_name` to `ReflectionProxy` classeileencodes2015-01-021-10/+0
| | | | | Putting the `#alias_name` into ReflectionProxy means we don't have to cache the `#alias_name` globally anymore - it's not cached per query.
* Refactor construct_tables methodeileencodes2015-01-021-0/+10
| | | | | Move method structure into reflection classes for accessibly on each reflection rather than by traversing the chain.
* Add PolymorphicReflection and constraints methodeileencodes2015-01-021-1/+58
| | | | | | `#constraints` builds a flattened version of `scope_chain` to allow it to be accessible without requiring an index when iterating over the `scope_chain`
* Merge pull request #15746 from amccloud/auto-inverse_of-in-moduleRafael Mendonça França2015-01-021-1/+1
|\ | | | | | | | | | | | | Fixed automatic inverse_of for models nested in module Conflicts: activerecord/CHANGELOG.md
| * Fixed automatic inverse_of for models nested in moduleAndrew McCloud2014-06-151-1/+1
| |
* | Add foreign_type option for polymorphic has_one and has_many.Ulisses Almeida + Kassio Borges2014-12-081-1/+1
| | | | | | | | | | | | | | To be possible to use a custom column name to save/read the polymorphic associated type in a has_many or has_one polymorphic association, now users can use the option :foreign_type to inform in what column the associated object type will be saved.
* | Fix grammar of sentence in Reflection documentationeileencodes2014-12-071-3/+3
| |
* | Pass symbol as an argument instead of a blockErik Michaels-Ober2014-11-291-1/+1
| |
* | Update reflections public API docArthur Neves2014-11-221-1/+1
| |
* | Improve the performance of reading attributesSean Griffin2014-11-181-1/+1
| | | | | | | | | | | | | | We added a comparison to "id", and call to `self.class.primary_key` a *lot*. We also have performance hits from `&block` all over the place. We skip the check in a new method, in order to avoid breaking the behavior of `read_attribute`
* | let's warn with heredocsXavier Noria2014-10-281-11/+19
| | | | | | | | | | | | | | | | | | | | | | | | The current style for warning messages without newlines uses concatenation of string literals with manual trailing spaces where needed. Heredocs have better readability, and with `squish` we can still produce a single line. This is a similar use case to the one that motivated defining `strip_heredoc`, heredocs are super clean.
* | Use if/else instead of early raiseRafael Mendonça França2014-10-151-2/+5
| |
* | Raise an error for has_one associations which try to go :through a ↵Tu Hoang2014-10-151-0/+1
| | | | | | | | polymorphic association [#17263]
* | Always add lambda to scope chain to eliminate branch in eval_scopeeileencodes2014-09-041-2/+5
| | | | | | | | | | | | We convert all other scopes to lambda's so it makes sense that we should always returns a lambda on a ThroughReflection as well. This eliminates the need to check if the scope is a Relation.
* | Avoid using heredoc for user warningsGodfrey Chan2014-08-281-15/+14
| | | | | | | | | | | | | | | | | | | | Using heredoc would enforce line wrapping to whatever column width we decided to use in the code, making it difficult for the users to read on some consoles. This does make the source code read slightly worse and a bit more error-prone, but this seems like a fair price to pay since the primary purpose for these messages are for the users to read and the code will not stick around for too long.
* | [ci skip] "..enables interrorgating of [thing].." would be correctZachary Scott2014-08-191-1/+1
| |