1. 01 12月, 2012 1 次提交
  2. 30 11月, 2012 4 次提交
    • J
      Use separate Relation subclasses for each AR class · 64c53d7c
      Jon Leighton 提交于
      At present, ActiveRecord::Delegation compiles delegation methods on a
      global basis. The compiled methods apply to all subsequent Relation
      instances. This creates several problems:
      
      1) After Post.all.recent has been called, User.all.respond_to?(:recent)
         will be true, even if User.all.recent will actually raise an error due
         to no User.recent method existing. (See #8080.)
      
      2) Depending on the AR class, the delegation should do different things.
         For example, if a Post.zip method exists, then Post.all.zip should call
         it. But this will then result in User.zip being called by a subsequent
         User.all.zip, even if User.zip does not exist, when in fact
         User.all.zip should call User.all.to_a.zip. (There are various
         variants of this problem.)
      
      We are creating these compiled delegations in order to avoid method
      missing and to avoid repeating logic on each invocation.
      
      One way of handling these issues is to add additional checks in various
      places to ensure we're doing the "right thing". However, this makes the
      compiled methods signficantly slower. In which case, there's almost no
      point in avoiding method_missing at all. (See #8127 for a proposed
      solution which takes this approach.)
      
      This is an alternative approach which involves creating a subclass of
      ActiveRecord::Relation for each AR class represented. So, with this
      patch, Post.all.class != User.all.class. This means that the delegations
      are compiled for and only apply to a single AR class. A compiled method
      for Post.all will not be invoked from User.all.
      
      This solves the above issues without incurring significant performance
      penalties. It's designed to be relatively seamless, however the downside
      is a bit of complexity and potentially confusion for a user who thinks
      that Post.all and User.all should be instances of the same class.
      
      Benchmark
      ---------
      
      require 'active_record'
      require 'benchmark/ips'
      
      class Post < ActiveRecord::Base
        establish_connection adapter: 'sqlite3', database: ':memory:'
        connection.create_table :posts
      
        def self.omg
          :omg
        end
      end
      
      relation = Post.all
      
      Benchmark.ips do |r|
        r.report('delegation')   { relation.omg }
        r.report('constructing') { Post.all }
      end
      
      Before
      ------
      
      Calculating -------------------------------------
                delegation      4392 i/100ms
              constructing      4780 i/100ms
      -------------------------------------------------
                delegation   144235.9 (±27.7%) i/s -     663192 in   5.038075s
              constructing   182015.5 (±21.2%) i/s -     850840 in   5.005364s
      
      After
      -----
      
      Calculating -------------------------------------
                delegation      6677 i/100ms
              constructing      6260 i/100ms
      -------------------------------------------------
                delegation   166828.2 (±34.2%) i/s -     754501 in   5.001430s
              constructing   116575.5 (±18.6%) i/s -     563400 in   5.036690s
      
      Comments
      --------
      
      Bear in mind that the standard deviations in the above are huge, so we
      can't compare the numbers too directly. However, we can conclude that
      Relation construction has become a little slower (as we'd expect), but
      not by a huge huge amount, and we can still construct a large number of
      Relations quite quickly.
      64c53d7c
    • J
      Fix memory leak in development mode · 68e4442e
      Jon Leighton 提交于
      Keying these hashes by klass causes reloadable classes to never get
      freed. Thanks to @thedarkone for pointing this out in
      the comments on 221571be.
      
      This doesn't seem to make a massive difference to performance.
      
      Benchmark
      ---------
      
      require 'active_record'
      require 'benchmark/ips'
      
      class Post < ActiveRecord::Base
        establish_connection adapter: 'sqlite3', database: ':memory:'
      end
      
      GC.disable
      
      Benchmark.ips(20) do |r|
        r.report { Post.connection }
      end
      
      Before
      ------
      
      Calculating -------------------------------------
                                5632 i/100ms
      -------------------------------------------------
                             218671.0 (±1.9%) i/s -    4364800 in  19.969401s
      
      After
      -----
      
      Calculating -------------------------------------
                                8743 i/100ms
      -------------------------------------------------
                             206525.9 (±17.8%) i/s -    4039266 in  19.992590s
      68e4442e
    • J
      Mark Relation mutators as :nodoc: · c5bdf6c5
      Jon Leighton 提交于
      These are for internal use only and cannot be relied on as part of the
      public API. See discussion on 8c2c6051.
      c5bdf6c5
    • A
      Revert "Fix annoy warning, when executing testcase." · da67d192
      Andrey Deryabin 提交于
      This reverts commit a3024f81.
      
      REASON: Since warning doesn't exist
      da67d192
  3. 29 11月, 2012 8 次提交
  4. 28 11月, 2012 4 次提交
  5. 27 11月, 2012 1 次提交
  6. 26 11月, 2012 4 次提交
  7. 25 11月, 2012 1 次提交
  8. 24 11月, 2012 2 次提交
  9. 22 11月, 2012 8 次提交
    • Y
      prevent mass assignment of polymorphic type when using `build` · 053bfa23
      Yves Senn 提交于
      Closes #8265
      053bfa23
    • C
      Remove the #sum method from CollectionAssociation · fd1c4576
      Carlos Antonio da Silva 提交于
      Since edd94cee, CollectionProxy
      delegates all calculation methods - except count - to the scope,
      which does basically what this method was doing, but since we're
      delegating from the proxy, the association method was never called.
      fd1c4576
    • C
      Deprecate Relation#sum with a block. · ad9983f6
      Carlos Antonio da Silva 提交于
      To perform a sum calculation over the array of elements, use to_a.sum(&block).
      
      Please check the discussion in f9cb645d
      for more context.
      ad9983f6
    • C
      Revert "Yield only one argument instead of splatting." · 76a6bfd6
      Carlos Antonio da Silva 提交于
      This reverts commit f9cb645d.
      
      Conflicts:
      	activerecord/CHANGELOG.md
      
      Revert "Allow blocks for count with ActiveRecord::Relation. Document and test that sum allows blocks"
      
      This reverts commit 9cc2bf69.
      
      Conflicts:
      	activerecord/lib/active_record/relation/calculations.rb
      76a6bfd6
    • J
      Don't allocate new strings in compiled attribute methods · ae934aef
      Jon Leighton 提交于
      This improves memory and performance without having to use symbols which
      present DoS problems. Thanks @headius and @tenderlove for the
      suggestion.
      
      This was originally committed in
      f1765019, and then reverted in
      d3494903 due to it causing problems in a
      real application. This second attempt should solve that.
      
      Benchmark
      ---------
      
      require 'active_record'
      require 'benchmark/ips'
      
      ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
      
      class Post < ActiveRecord::Base
        connection.create_table :posts, force: true do |t|
          t.string :name
        end
      end
      
      post = Post.create name: 'omg'
      
      Benchmark.ips do |r|
        r.report('Post.new')          { Post.new name: 'omg' }
        r.report('post.name')         { post.name }
        r.report('post.name=')        { post.name = 'omg' }
        r.report('Post.find(1).name') { Post.find(1).name }
      end
      
      Before
      ------
      
      Calculating -------------------------------------
                  Post.new      1419 i/100ms
                 post.name      7538 i/100ms
                post.name=      3024 i/100ms
         Post.find(1).name       243 i/100ms
      -------------------------------------------------
                  Post.new    20637.6 (±12.7%) i/s -     102168 in   5.039578s
                 post.name  1167897.7 (±18.2%) i/s -    5186144 in   4.983077s
                post.name=    64305.6 (±9.6%) i/s -     317520 in   4.998720s
         Post.find(1).name     2678.8 (±10.8%) i/s -      13365 in   5.051265s
      
      After
      -----
      
      Calculating -------------------------------------
                  Post.new      1431 i/100ms
                 post.name      7790 i/100ms
                post.name=      3181 i/100ms
         Post.find(1).name       245 i/100ms
      -------------------------------------------------
                  Post.new    21308.8 (±12.2%) i/s -     105894 in   5.053879s
                 post.name  1534103.8 (±2.1%) i/s -    7634200 in   4.979405s
                post.name=    67441.0 (±7.5%) i/s -     337186 in   5.037871s
         Post.find(1).name     2681.9 (±10.6%) i/s -      13475 in   5.084511s
      ae934aef
    • C
      96106a14
    • S
      Coerce strings in create_join_table. · 48a03571
      Steve Klabnik 提交于
      If you accidentally pass a string and a symbol, this breaks. So
      we coerce them both to strings.
      
      Fixes #7715
      48a03571
    • C
      Typo · 104f4fde
      Chris Patuzzo 提交于
      104f4fde
  10. 21 11月, 2012 3 次提交
  11. 20 11月, 2012 2 次提交
  12. 19 11月, 2012 2 次提交