1. 23 5月, 2017 1 次提交
  2. 07 5月, 2017 1 次提交
  3. 03 1月, 2017 1 次提交
    • K
      Cache results of computing model type · cdf8a2b4
      Konstantin Lazarev 提交于
      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
      ```
      cdf8a2b4
  4. 16 8月, 2016 1 次提交
  5. 07 8月, 2016 3 次提交
  6. 15 3月, 2016 1 次提交
  7. 28 1月, 2016 1 次提交
    • S
      Do not use default attributes for STI when instantiating a subclass · 77383fc1
      Sean Griffin 提交于
      The commit which originally added this behavior did not consider that
      doing `Subclass.new` does not actually populate the `type` field in the
      attributes (though perhaps it should). We simply need to not use the
      defaults for STI related things unless we are instantiating the base
      class.
      
      Fixes #23285.
      77383fc1
  8. 20 1月, 2016 2 次提交
  9. 03 12月, 2015 1 次提交
  10. 02 12月, 2015 1 次提交
  11. 31 10月, 2015 1 次提交
  12. 27 10月, 2015 2 次提交
  13. 13 5月, 2015 1 次提交
  14. 11 5月, 2015 1 次提交
    • A
      allow setting of a demodulized class name when using STI · cbd66b43
      Alex Robbin 提交于
      If your STI class looks like this:
      
      ```ruby
      class Company < ActiveRecord::Base
        self.store_full_sti_class = false
      
        class GoodCo < Company
        end
      
        class BadCo < Company
        end
      end
      ```
      
      The expectation (which is valid) is that the `type` in the database is saved as
      `GoodCo` or `BadCo`. However, another expectation should be that setting `type`
      to `GoodCo` would correctly instantiate the object as a `Company::GoodCo`. That
      second expectation is what this should fix.
      cbd66b43
  15. 07 5月, 2015 1 次提交
    • Y
      tests, extract helpers to modify global state. · d27974d3
      Yves Senn 提交于
      Make sure that tests do not hardcode the default value.
      For example `test_instantiation_doesnt_try_to_require_corresponding_file`
      always restored the configuration to `true` regardless of what it's
      original value was.
      
      Extract a helper to make the global modification consistent across tests.
      d27974d3
  16. 04 2月, 2015 1 次提交
    • M
      Always reset changed attributes in becomes · 5f6370a8
      Miklos Fazekas 提交于
      When ```becomes``` changes @attributes it should also change
      @changed_attributes. Otherwise we'll experience a kind of split head situation
      where attributes are coming from ```self```, but changed_attributes is coming
      from ```klass.new```. This affects the inheritance_colmn as it's changed by new
      for example.
      
      Fixes #16881
      5f6370a8
  17. 27 1月, 2015 1 次提交
  18. 27 12月, 2014 1 次提交
  19. 19 11月, 2014 1 次提交
    • S
      Improve the performance of reading attributes · 08576b94
      Sean Griffin 提交于
      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`
      08576b94
  20. 29 9月, 2014 1 次提交
    • B
      Isolate access to @associations_cache and @aggregations cache to the... · 9d569585
      Ben Woosley 提交于
      Isolate access to @associations_cache and @aggregations cache to the Associations and Aggregations modules, respectively.
      
      This includes replacing the `association_cache` accessor with a more
      limited `association_cached?` accessor and making `clear_association_cache`
      and `clear_aggregation_cache` private.
      9d569585
  21. 18 5月, 2014 1 次提交
  22. 15 3月, 2014 1 次提交
  23. 22 1月, 2014 1 次提交
    • J
      Ensure AR #second, #third, etc. finders work through associations · 03855e79
      Jason Meller 提交于
      This commit fixes two regressions introduced in cafe31a0 where
      newly created finder methods #second, #third, #forth, and #fifth
      caused a NoMethodError error on reload associations and where we
      were pulling the wrong element out of cached associations.
      
      Examples:
      
        some_book.authors.reload.second
      
        # Before
        # => NoMethodError: undefined method 'first' for nil:NilClass
      
        # After
        # => #<Author id: 2, name: "Sally Second", ...>
      
        some_book.first.authors.first
        some_book.first.authors.second
      
        # Before
        # => #<Author id: 1, name: "Freddy First", ...>
        # => #<Author id: 1, name: "Freddy First", ...>
      
        # After
        # => #<Author id: 1, name: "Freddy First", ...>
        # => #<Author id: 2, name: "Sally Second", ...>
      
      Fixes #13783.
      03855e79
  24. 14 1月, 2014 1 次提交
    • U
      Don't try to get the subclass if the inheritance column doesn't exist · e8d1d848
      Ujjwal Thaakar 提交于
      The `subclass_from_attrs` method is called even if the column specified by
      the `inheritance_column` setting doesn't exist. This prevents setting associations
      via the attributes hash if the association name clashes with the value of the setting,
      typically `:type`. This worked previously in Rails 3.2.
      e8d1d848
  25. 13 1月, 2014 1 次提交
  26. 04 1月, 2014 1 次提交
  27. 04 10月, 2013 1 次提交
  28. 02 4月, 2013 1 次提交
  29. 18 3月, 2013 1 次提交
  30. 11 3月, 2013 1 次提交
  31. 06 3月, 2013 1 次提交
  32. 29 11月, 2012 2 次提交
  33. 26 10月, 2012 1 次提交
    • J
      Remove ActiveRecord::Model · 9e4c41c9
      Jon Leighton 提交于
      In the end I think the pain of implementing this seamlessly was not
      worth the gain provided.
      
      The intention was that it would allow plain ruby objects that might not
      live in your main application to be subclassed and have persistence
      mixed in. But I've decided that the benefit of doing that is not worth
      the amount of complexity that the implementation introduced.
      9e4c41c9
  34. 04 9月, 2012 2 次提交