1. 24 4月, 2019 7 次提交
  2. 22 4月, 2019 5 次提交
    • R
      5454cc40
    • R
      70e255b9
    • R
      Remove useless `set_value` / `get_value` helper methods · 89b86640
      Ryuta Kamizono 提交于
      Those helper methods makes relation values access 15% slower.
      
      https://gist.github.com/kamipo/e64439f7a206e1c5b5c69d92d982828e
      
      Before (02b5b8cb):
      
      ```
      Warming up --------------------------------------
              #limit_value   237.074k i/100ms
          #limit_value = 1   222.052k i/100ms
      Calculating -------------------------------------
              #limit_value      6.477M (± 2.9%) i/s -     32.479M in   5.019475s
          #limit_value = 1      5.297M (± 4.3%) i/s -     26.424M in   4.999933s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
              #limit_value   261.109k i/100ms
          #limit_value = 1   239.646k i/100ms
      Calculating -------------------------------------
              #limit_value      7.412M (± 1.6%) i/s -     37.077M in   5.003345s
          #limit_value = 1      6.134M (± 1.0%) i/s -     30.675M in   5.000908s
      ```
      89b86640
    • R
      PERF: 20% faster pk attribute access · b6828fc9
      Ryuta Kamizono 提交于
      I've realized that `user.id` is 20% slower than `user.name` in the
      benchmark (https://github.com/rails/rails/pull/35987#issuecomment-483882480).
      
      The reason that performance difference is that `self.class.primary_key`
      method call is a bit slow.
      
      Avoiding that method call will make almost attribute access faster and
      `user.id` will be completely the same performance with `user.name`.
      
      Before (02b5b8cb):
      
      ```
      Warming up --------------------------------------
                   user.id   140.535k i/100ms
                user['id']    96.549k i/100ms
                 user.name   158.110k i/100ms
              user['name']    94.507k i/100ms
             user.changed?    19.003k i/100ms
       user.saved_changes?    25.404k i/100ms
      Calculating -------------------------------------
                   user.id      2.231M (± 0.9%) i/s -     11.243M in   5.040066s
                user['id']      1.310M (± 1.3%) i/s -      6.565M in   5.012607s
                 user.name      2.683M (± 1.2%) i/s -     13.439M in   5.009392s
              user['name']      1.322M (± 0.9%) i/s -      6.615M in   5.003239s
             user.changed?    201.999k (±10.9%) i/s -      1.007M in   5.091195s
       user.saved_changes?    258.214k (±17.1%) i/s -      1.245M in   5.007421s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
                   user.id   158.364k i/100ms
                user['id']   106.412k i/100ms
                 user.name   158.644k i/100ms
              user['name']   107.518k i/100ms
             user.changed?    19.082k i/100ms
       user.saved_changes?    24.886k i/100ms
      Calculating -------------------------------------
                   user.id      2.768M (± 1.1%) i/s -     13.936M in   5.034957s
                user['id']      1.507M (± 2.1%) i/s -      7.555M in   5.017211s
                 user.name      2.727M (± 1.5%) i/s -     13.643M in   5.004766s
              user['name']      1.521M (± 1.3%) i/s -      7.634M in   5.018321s
             user.changed?    200.865k (±11.1%) i/s -    992.264k in   5.044868s
       user.saved_changes?    269.652k (±10.5%) i/s -      1.344M in   5.077972s
      ```
      b6828fc9
    • R
      Remove never used `database_selector` class accessor · 02b5b8cb
      Ryuta Kamizono 提交于
      It was never used from the beginning.
      02b5b8cb
  3. 21 4月, 2019 1 次提交
    • R
      Avoid method call if `@transaction_state` is not finalized · f9326e56
      Ryuta Kamizono 提交于
      Method call in Ruby is a bit slow.
      
      This makes attribute access 10% faster by avoiding method call
      (`sync_with_transaction_state`).
      
      Before (96cf7e0e):
      
      ```
      Warming up --------------------------------------
                   user.id   131.291k i/100ms
                user['id']    91.786k i/100ms
                 user.name   151.605k i/100ms
              user['name']    92.664k i/100ms
             user.changed?    17.772k i/100ms
       user.saved_changes?    23.909k i/100ms
      Calculating -------------------------------------
                   user.id      1.988M (± 7.0%) i/s -      9.978M in   5.051474s
                user['id']      1.155M (± 5.8%) i/s -      5.783M in   5.022672s
                 user.name      2.450M (± 4.3%) i/s -     12.280M in   5.021234s
              user['name']      1.263M (± 2.1%) i/s -      6.394M in   5.066638s
             user.changed?    175.070k (±13.3%) i/s -    853.056k in   5.011555s
       user.saved_changes?    259.114k (±11.8%) i/s -      1.267M in   5.001260s
      ```
      
      After (this change):
      
      ```
      Warming up --------------------------------------
                   user.id   137.625k i/100ms
                user['id']    96.054k i/100ms
                 user.name   156.379k i/100ms
              user['name']    94.795k i/100ms
             user.changed?    18.172k i/100ms
       user.saved_changes?    24.337k i/100ms
      Calculating -------------------------------------
                   user.id      2.201M (± 0.5%) i/s -     11.010M in   5.002955s
                user['id']      1.320M (± 1.0%) i/s -      6.628M in   5.021293s
                 user.name      2.677M (± 1.6%) i/s -     13.449M in   5.024399s
              user['name']      1.314M (± 1.8%) i/s -      6.636M in   5.051444s
             user.changed?    190.588k (±11.1%) i/s -    944.944k in   5.065848s
       user.saved_changes?    262.782k (±12.1%) i/s -      1.290M in   5.028080s
      ```
      f9326e56
  4. 20 4月, 2019 3 次提交
    • A
    • E
      Remove description for namespaced `db:migrate:up` · 5cc74660
      eileencodes 提交于
      This was accidentally left in, the standard `db:migrate:up` doesn't have
      a description so `db:migrate:up:namespace` shouldn't have one either.
      5cc74660
    • E
      Handle up/down for multiple databases · f9244c65
      eileencodes 提交于
      This change adds the ability to run up/down for a database in a multi-db
      environment.
      
      If you have an app with a primary and animals database the following
      tasks will be generated:
      
      ```
      VERSION=123 rake db:migrate:up:primary
      VERSION=123 rake db:migrate:up:primary
      
      VERSION=123 rake db:migrate:down:primary
      VERSION=123 rake db:migrate:up:animals
      ```
      
      I didn't generate descriptions with them since we don't generate a
      description for a single database application.
      
      In addition to this change I've made it so if your application has
      multiple databases Rails will raise if you try to run `up` or `down`
      without a namespace. This is because we don't know which DB you want to
      run `up` or `down` against unless the app tells us, so it's safer to
      just block it and recommend using namespaced versions of up/down
      respectively.
      
      The output for the raise looks like:
      
      ```
      You're using a multiple database application. To use `db:migrate:down`
      you must run the namespaced task with a VERSION. Available tasks are
      db:migrate:down:primary and db:migrate:down:animals.
      ```
      f9244c65
  5. 19 4月, 2019 8 次提交
    • R
    • R
      Deprecate `collection_cache_key` which is private API · f656bb30
      Ryuta Kamizono 提交于
      The `collection_cache_key` is private API for a long time, but I've
      maintained it in #35848 since it is mentioned in the doc
      (https://github.com/rails/rails/pull/35848#discussion_r272011475).
      
      The doc has removed at 1da9a7e4, so there is no longer a reason to
      maintain that private API.
      f656bb30
    • R
      Give GeneratedRelationMethods module a name · 607d77ab
      Ryuta Kamizono 提交于
      This follows #35595.
      607d77ab
    • R
      Revert renamed `GeneratedAttributeMethods` · 2733a68f
      Ryuta Kamizono 提交于
      This partly reverts 8ca3c286.
      
      `.is_a?(GeneratedAttributeMethodsBuilder)` doesn't make sense to me, the
      module class's `new` creates just an instance of the module class itself.
      2733a68f
    • G
      255a2422
    • G
      Introduce Actionable Errors · 45f1c7a3
      Genadi Samokovarov 提交于
      Actionable errors let's you dispatch actions from Rails' error pages. This
      can help you save time if you have a clear action for the resolution of
      common development errors.
      
      The de-facto example are pending migrations. Every time pending migrations
      are found, a middleware raises an error. With actionable errors, you can
      run the migrations right from the error page. Other examples include Rails
      plugins that need to run a rake task to setup themselves. They can now
      raise actionable errors to run the setup straight from the error pages.
      
      Here is how to define an actionable error:
      
      ```ruby
      class PendingMigrationError < MigrationError #:nodoc:
        include ActiveSupport::ActionableError
      
        action "Run pending migrations" do
          ActiveRecord::Tasks::DatabaseTasks.migrate
        end
      end
      ```
      
      To make an error actionable, include the `ActiveSupport::ActionableError`
      module and invoke the `action` class macro to define the action. An action
      needs a name and a procedure to execute. The name is shown as the name of a
      button on the error pages. Once clicked, it will invoke the given
      procedure.
      45f1c7a3
    • R
      Deprecate `where.not` working as NOR and will be changed to NAND in Rails 6.1 · 12a9664f
      Ryuta Kamizono 提交于
      `where.not` with polymorphic association is partly fixed incidentally at
      213796fb (refer #33493, #26207, #17010, #16983, #14161), and I've added
      test case e9ba12f7 to avoid lose that fix accidentally in the future.
      
      In Rails 5.2, `where.not(polymorphic: object)` works as expected as
      NAND, but `where.not(polymorphic_type: object.class.polymorphic_name,
      polymorphic_id: object.id)` still unexpectedly works as NOR.
      
      To will make `where.not` working desiredly as NAND in Rails 6.1, this
      deprecates `where.not` working as NOR. If people want to continue NOR
      conditions, we'd encourage to them to `where.not` each conditions
      manually.
      
      ```ruby
      all = [treasures(:diamond), treasures(:sapphire), cars(:honda), treasures(:sapphire)]
      assert_equal all, PriceEstimate.all.map(&:estimate_of)
      ```
      
      In Rails 6.0:
      
      ```ruby
      sapphire = treasures(:sapphire)
      
      nor = all.reject { |e|
        e.estimate_of_type == sapphire.class.polymorphic_name
      }.reject { |e|
        e.estimate_of_id == sapphire.id
      }
      assert_equal [cars(:honda)], nor
      
      without_sapphire = PriceEstimate.where.not(
        estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id
      )
      assert_equal nor, without_sapphire.map(&:estimate_of)
      ```
      
      In Rails 6.1:
      
      ```ruby
      sapphire = treasures(:sapphire)
      
      nand = all - [sapphire]
      assert_equal [treasures(:diamond), cars(:honda)], nand
      
      without_sapphire = PriceEstimate.where.not(
        estimate_of_type: sapphire.class.polymorphic_name, estimate_of_id: sapphire.id
      )
      assert_equal nand, without_sapphire.map(&:estimate_of)
      ```
      
      Resolves #31209.
      12a9664f
    • E
      Ensure active record can load without Railties · 456c3f10
      eileencodes 提交于
      When I added the rake tasks for multiple databases I accidentally made
      it so you couldn't use Active Record without Railties.
      
      Since getting the database configuration depends on being able to load
      Railties (there is no other way to read and parse the yaml file and load
      it) I've decided that using multiple databases outside of Rails is a
      no-op.
      
      I've changed the code here to return if Rails isn't defined. Then I
      changed the other tasks to use `ActiveRecord::Tasks::DatabaseTasks.env`
      instead of `Rails.env`. The multi-db tasks can keep using `Rails.env`
      because they'll only be generated if we're using Rails and not just
      Active Record.
      456c3f10
  6. 17 4月, 2019 2 次提交
    • G
    • L
      Add collection cache versioning · 4f2ac80d
      Lachlan Sylvester 提交于
      Cache versioning enables the same cache key to be reused when the object
      being cached changes by moving the volatile part of the cache key out of
      the cache key and into a version that is embedded in the cache entry.
      
      This is already occurring when the object being cached is an
      `ActiveRecord::Base`, but when caching an `ActiveRecord::Relation`
      we are currently still putting the volatile information (max updated at
      and count) as part of the cache key.
      
      This PR moves the volatile part of the relations `cache_key` into the
      `cache_version` to support recycling cache keys for
      `ActiveRecord::Relation`s.
      4f2ac80d
  7. 16 4月, 2019 4 次提交
    • S
      b2aa46ff
    • R
      Fix dirty tracking after rollback. · 63ff495b
      Ryuta Kamizono 提交于
      Currently the rollback only restores primary key value, `new_record?`,
      `destroyed?`, and `frozen?`. Since the `save` clears current dirty
      attribute states, retrying save after rollback will causes no change
      saved if partial writes is enabled (by default).
      
      This makes `remember_transaction_record_state` remembers original values
      then restores dirty attribute states after rollback.
      
      Fixes #15018.
      Fixes #30167.
      Fixes #33868.
      Fixes #33443.
      Closes #33444.
      Closes #34504.
      63ff495b
    • R
      Don't refer `@transaction_state` directly · f7e126be
      Ryuta Kamizono 提交于
      Since 8180c396, remaining transaction state is cleared in
      `force_clear_transaction_record_state` to less work
      `sync_with_transaction_state`. But it caused a race condition that
      `@transaction_state` would be cleared by other threads if the state is
      finalized.
      
      To work as before, snapshot `@transaction_state` to local variable not
      to refer `@transaction_state` directly.
      
      Fixes #35983.
      f7e126be
    • J
      Find query_source_location using lazy Enumerator · 0bab6310
      John Hawthorn 提交于
      This way, we only need to filter the backtrace up to the first non-noise
      stack frame.
      
      This also updates noise to be able to deal with being passed a lazy
      enum. We don't need this anywhere, but it seemed better for this to be
      consistent.
      0bab6310
  8. 15 4月, 2019 4 次提交
  9. 14 4月, 2019 2 次提交
  10. 13 4月, 2019 2 次提交
    • Y
      use PostgreSQL's bulk_alter_table implementation · 53f1b3e5
      Yoshiyuki Kinjo 提交于
      Running this migration on mysql at current master fails
      because `add_references_for_alter` is missing.
      
      ```
      change_table :users, bulk: true do |t|
        t.references :article
      end
      ```
      
      This is also true for postgresql adapter,
      but its `bulk_alter_table` implementation can fallback in such case.
      postgresql's implementation is desirable to prevent unknown failure like this.
      53f1b3e5
    • C
      Improve wording of comments · c9d75177
      Chris Salzberg 提交于
      Most of the time, these methods are called from actual methods defined
      from columns in the schema, not from method_missing, so the current
      wording is misleading.
      c9d75177
  11. 12 4月, 2019 2 次提交