aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/has_many_through_association.rb
Commit message (Collapse)AuthorAgeFilesLines
* Add missing source_type if provided on hmt which belongs to an sti recordVipul A M2016-01-241-0/+5
| | | | Fixes #23209
* HasManyAssociation: moved half of counter cache code to reflectionBogdan Gusiev2015-09-031-1/+1
| | | | | | | | | | | | | | | | | | 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.
* Revert "Revert "Reduce allocations when running AR callbacks.""Guo Xiang Tan2015-07-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reverts commit bdc1d329d4eea823d07cf010064bd19c07099ff3. Before: Calculating ------------------------------------- 22.000 i/100ms ------------------------------------------------- 229.700 (± 0.4%) i/s - 1.166k Total Allocated Object: 9939 After: Calculating ------------------------------------- 24.000 i/100ms ------------------------------------------------- 246.443 (± 0.8%) i/s - 1.248k Total Allocated Object: 7939 ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' # gem 'rails', github: 'rails/rails', ref: 'bdc1d329d4eea823d07cf010064bd19c07099ff3' gem 'rails', github: 'rails/rails', ref: 'd2876141d08341ec67cf6a11a073d1acfb920de7' gem 'arel', github: 'rails/arel' gem 'sqlite3' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('sqlite3::memory:') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.boolean :admin t.timestamps null: false end end class User < ActiveRecord::Base default_scope { where(admin: true) } end admin = true 1000.times do attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", admin: admin } User.create!(attributes) admin = !admin end GC.disable Benchmark.ips(5, 3) do |x| x.report { User.all.to_a } end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.all.to_a after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ```
* Autosave existing records on HMT associations when the parent is newSean Griffin2015-04-181-6/+4
| | | | | | | | | | | | | | | To me it seems like this should only be the case if `autosave: true` is set on the association. However, when implemented that way, it caused issues with has many associations, where we have explicit tests stating that child records are updated when the parent is new, even if autosave is not set (presumably to update the parent id, but other changed attributes would be persisted as well). It's quirky, but at least we should be consistently quirky. This constitutes a minor but subtle change in behavior, and therefore should not be backported to 4.2 and earlier. Fixes #19782
* Revert "Reduce allocations when running AR callbacks."Guo Xiang Tan2015-03-221-1/+1
| | | | This reverts commit 796cab45561fce268aa74e6587cdb9cae3bb243e.
* Correct errors in counter cache updatingSean Griffin2015-02-031-2/+2
| | | | | | | | | | | The cache name should be converted to a string when given, not compared as a symbol. This edge case is already adequately covered by our tests, but was masked by another issue where we were incorrectly updating the counter cache twice. When paired with a bug where we didn't update the counter cache because we couldn't find a match with the name, this made it look like everything was working fine. Fixes #10865.
* Remove Relation#bind_paramsSean Griffin2015-01-271-1/+1
| | | | | | | | `bound_attributes` is now used universally across the board, removing the need for the conversion layer. These changes are mostly mechanical, with the exception of the log subscriber. Additional, we had to implement `hash` on the attribute objects, so they could be used as a key for query caching.
* Remove unneeded requiresRafael Mendonça França2015-01-041-2/+0
| | | | These requires were added only to change deprecation message
* Remove deprecated automatic counter caches on `has_many :through`Rafael Mendonça França2015-01-041-14/+0
|
* Remove unneeded special case to calculate size for has_many :throughBogdan Gusiev2014-12-231-15/+0
| | | | | All cases are properly handled in CollectionAssociation for all subclasses of this association
* Update Arel usage for rails/arel#98fc259Sean Griffin2014-11-291-1/+1
| | | | | `where_sql` now requires that we pass it an engine. None of the manager classes take an engine in their constructor.
* Pass symbol as an argument instead of a blockErik Michaels-Ober2014-11-291-3/+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`
* Avoid unnecessary allocations/callsPablo Herrero2014-11-021-1/+1
|
* edit pass over all warningsXavier Noria2014-10-281-3/+3
| | | | | | | | | | | | | | | This patch uniformizes warning messages. I used the most common style already present in the code base: * Capitalize the first word. * End the message with a full stop. * "Rails 5" instead of "Rails 5.0". * Backticks for method names and inline code. Also, converted a few long strings into the new heredoc convention.
* let's warn with heredocsXavier Noria2014-10-281-5/+8
| | | | | | | | | | | | 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.
* Prefix internal method with _Rafael Mendonça França2014-10-251-1/+1
| | | | This will avoid naming clash with user defined methods
* Reduce allocations when running AR callbacks.Pete Higgins2014-09-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Inspired by @tenderlove's work in c363fff29f060e6a2effe1e4bb2c4dd4cd805d6e, this reduces the number of strings allocated when running callbacks for ActiveRecord instances. I measured that using this script: ``` require 'objspace' require 'active_record' require 'allocation_tracer' ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:" ActiveRecord::Base.connection.instance_eval do create_table(:articles) { |t| t.string :name } end class Article < ActiveRecord::Base; end a = Article.create name: "foo" a = Article.find a.id N = 10 result = ObjectSpace::AllocationTracer.trace do N.times { Article.find a.id } end result.sort.each do |k,v| p k => v end puts "total: #{result.values.map(&:first).inject(:+)}" ``` When I run this against master and this branch I get this output: ``` pete@balloon:~/projects/rails/activerecord$ git checkout master M Gemfile Switched to branch 'master' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_before pete@balloon:~/projects/rails/activerecord$ git checkout remove-dynamic-send-on-built-in-callbacks M Gemfile Switched to branch 'remove-dynamic-send-on-built-in-callbacks' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_after pete@balloon:~/projects/rails/activerecord$ diff allocations_before allocations_after 39d38 < {["/home/pete/projects/rails/activesupport/lib/active_support/callbacks.rb", 81]=>[40, 0, 0, 0, 0, 0]} 42c41 < total: 630 --- > total: 590 ``` In addition to this, there are two micro-optimizations present: * Using `block.call if block` vs `yield if block_given?` when the block was being captured already. ``` pete@balloon:~/projects$ cat benchmark_block_call_vs_yield.rb require 'benchmark/ips' def block_capture_with_yield &block yield if block_given? end def block_capture_with_call &block block.call if block end def no_block_capture yield if block_given? end Benchmark.ips do |b| b.report("block_capture_with_yield") { block_capture_with_yield } b.report("block_capture_with_call") { block_capture_with_call } b.report("no_block_capture") { no_block_capture } end pete@balloon:~/projects$ ruby benchmark_block_call_vs_yield.rb Calculating ------------------------------------- block_capture_with_yield 124979 i/100ms block_capture_with_call 138340 i/100ms no_block_capture 136827 i/100ms ------------------------------------------------- block_capture_with_yield 5703108.9 (±2.4%) i/s - 28495212 in 4.999368s block_capture_with_call 6840730.5 (±3.6%) i/s - 34169980 in 5.002649s no_block_capture 5821141.4 (±2.8%) i/s - 29144151 in 5.010580s ``` * Defining and calling methods instead of using send. ``` pete@balloon:~/projects$ cat benchmark_method_call_vs_send.rb require 'benchmark/ips' class Foo def tacos nil end end my_foo = Foo.new Benchmark.ips do |b| b.report('send') { my_foo.send('tacos') } b.report('call') { my_foo.tacos } end pete@balloon:~/projects$ ruby benchmark_method_call_vs_send.rb Calculating ------------------------------------- send 97736 i/100ms call 151142 i/100ms ------------------------------------------------- send 2683730.3 (±2.8%) i/s - 13487568 in 5.029763s call 8005963.9 (±2.7%) i/s - 40052630 in 5.006604s ``` The result of this is making typical ActiveRecord operations slightly faster: https://gist.github.com/phiggins/e46e51dcc7edb45b5f98
* Avoid using heredoc for user warningsGodfrey Chan2014-08-281-6/+6
| | | | | | | | | | 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.
* remove blank lines in the start of the ActiveRecord filesPonomarev Nikolay2014-07-291-1/+0
|
* Deprecate automatic counter caches on has_many :throughSean Griffin2014-06-261-0/+14
| | | | | | | | | | | Reliant on https://github.com/rails/rails/pull/15747 but pulled to a separate PR to reduce noise. `has_many :through` associations have the undocumented behavior of automatically detecting counter caches. However, the way in which it does so is inconsistent with counter caches everywhere else, and doesn't actually work consistently. As with normal `has_many` associations, the user should specify the counter cache on the `belongs_to`, if they'd like it updated.
* Merge pull request #15747 from sgrif/sg-trolololol-this-is-so-brokenRafael Mendonça França2014-06-191-1/+0
|\ | | | | Always update counter caches in memory when adding records
| * Always update counter caches in memory when adding recordsSean Griffin2014-06-161-1/+0
| | | | | | | | | | | | | | | | | | | | | | Before, calling `size` would only work if it skipped the cache, and would return a different result from the cache, but only if: - The association was previously loaded - Or you called size previously - But only if the size was 0 when you called it This ensures that the counter is appropriately updated in memory.
* | Merge pull request #15772 from nbudin/sti_through_bugRafael Mendonça França2014-06-191-1/+3
|\ \ | |/ |/| | | Don't include inheritance column in the through_scope_attributes
| * Don't include inheritance column in the through_scope_attributesNat Budin2014-06-171-1/+1
|/
* Merge pull request #15701 from zzak/issue_15496Rafael Mendonça França2014-06-131-1/+5
|\ | | | | Open extension point for defining options in build_through_record
| * Open extension point for defining options in build_through_recordZachary Scott2014-06-131-1/+5
| | | | | | | | This fixes #15496
* | Through associations should set both parent ids on join modelsSean Griffin2014-06-131-1/+5
|/ | | | | | | | | | | | | member = Member.new(club: Club.new) member.save! Before: member.current_membership.club_id # => nil After: member.current_membership.club_id # => club's id
* reuse available collection? check instead of macroeileencodes2014-06-091-3/+3
| | | | | | | Reflection has an available method that is used to check if the reflection is a collection. Any :has_many macro is considered a collection and `collection?` should be used instead of `macro == :has_many`.
* add has_one? method and reuse instead of checking macroeileencodes2014-06-091-1/+1
| | | | | | Instead of checking for `macro == :has_one` throughout the codebase we can create a `has_one?` method to match the `belongs_to?`, `polymorphic?` and other methods.
* Do not try to set the foreign_key again on has_many throughRafael Mendonça França2014-06-091-1/+1
| | | | | | | Integration tests are inside protected_attributes test suite. Fixes #15496 Fixes rails/protected_attributes#35
* reuse available belongs_to? methodeileencodes2014-06-031-1/+1
| | | | | | | | | | Reflection has a `belongs_to?` method. Instead of checking for `macro == :belongs_to` throughout the source reuse existing method. I also bumped `foreign_key_present?` method onto on line because the `belongs_to?` makes it shorter than other longer lines in the same class.
* rename delete_all_records to delete_or_nullify_all_recordseileencodes2014-05-131-6/+2
| | | | | | | Rename delete_all_records because this name better describes what the method is doing. We can then remove :all from the hm:t version and pull out the unoptimized call to load_target in delete_records and pass it directly.
* begin refactoring delete_records methodeileencodes2014-05-131-0/+4
| | | | | | | | | | | | | | Refactor by creating two methods delete_all_records and delete_records to be called by delete_all and delete (or destroy) respectively. This reduces the number of conditionals required to handle _how_ records get deleted. The new delete_count method handles how scope is applied to which delete action. A delete_all_records method also has to be called in has_many_through association because of how the methods are chained. This will be refactored later on.
* Fixed HABTM's CollectionAssociation sizeFred Wu2014-05-081-1/+1
| | | | | HABTM should fall back to using the normal CollectionAssociation's size calculation if the collection is not cached or loaded. This addresses both #14913 and #14914 for master.
* Follow-up to #14990 [ci skip]Jon Atack2014-05-071-10/+9
| | | | | | | | Rewrite to avoid 'we'/'you', add missing period, and keep lines at 80 chars. Cheers :) Improve readability with help from @senny [ci skip]
* Fixed grammarFred Wu2014-05-061-1/+1
|
* use cache queries for hm:t associationsAaron Patterson2014-04-151-1/+1
|
* again, read_attribute is public, so just call itAaron Patterson2014-04-131-1/+1
|
* Merge pull request #12829 from iantropov/issue_insert_via_hmt_scope_3548Rafael Mendonça França2014-04-101-1/+5
|\ | | | | | | | | | | | | Fix insertion of records for hmt association with scope Conflicts: activerecord/CHANGELOG.md
| * Fix insertion of records for hmt association with scope, fix #3548Ivan Antropov2013-11-171-1/+5
| |
* | let `insert_record` actuall save the object.Aaron Patterson2014-02-251-2/+1
|/ | | | | | | | | | `before_add` callbacks are fired before the record is saved on `has_and_belongs_to_many` assocations *and* on `has_many :through` associations. Before this change, `before_add` callbacks would be fired before the record was saved on `has_and_belongs_to_many` associations, but *not* on `has_many :through` associations. Fixes #14144
* Prevent the counter cache from being decremented twicedm1try2013-11-111-1/+1
| | | | | when destroying a record on a has_many :through association. :destroy method has own counter_cache callbacks.
* fix deleting join models with no pkAaron Patterson2013-09-111-1/+15
|
* Adding a bang to method name of raise_on_type_mismatch.wangjohn2013-03-211-1/+1
|
* Reverting 16f6f25 (Change behaviour with empty array in where clause)Guillermo Iguaran2013-02-081-1/+1
|
* Change behaviour with empty array in where clauserobertomiranda2013-02-081-1/+1
|
* target_reflection_has_associated_record? refactoringAngelo Capilleri2013-01-081-5/+1
|
* Fix for has_many_through counter_cache bugMatthew Robertson2012-12-141-0/+5
| | | | | | This commit fixes reported issue #7630 in which counter caches were not being updated properly when replacing has_many_through relationships
* Merge pull request #7251 from rails/integrate-strong_parametersDavid Heinemeier Hansson2012-09-181-2/+2
|\ | | | | Integrate strong_parameters in Rails 4