1. 05 3月, 2020 1 次提交
  2. 04 3月, 2020 1 次提交
    • E
      Refactor invert predicate · 27fb3563
      eileencodes 提交于
      Instead of doing a case statement here we can have each of the objects
      respond to `invert`. This means that when adding new objects we don't
      need to increase this case statement, it's more object oriented, and
      let's be fair, it looks better too.
      
      Aaron and I stumbled upon this while working on some performance
      work in Arel.
      
      I removed `random_object` from the invert test because we don't support
      random objects. If you pass a random object to Arel, it should raise,
      not be inverted.
      Co-authored-by: NAaron Patterson <aaron.patterson@gmail.com>
      27fb3563
  3. 03 3月, 2020 1 次提交
  4. 02 3月, 2020 1 次提交
    • B
      Add activerecord/db/ to gitignore · 22877a9d
      bogdanvlviv 提交于
      After running `bundle exec rake test:sqlite3` and `bundle exec rake test:sqlite3_mem`
      on my VM I noticed that it had created untracked files:
      
      ```bash
      vagrant@ubuntu-bionic:/rails/activerecord$ git status
      Untracked files:
        (use "git add <file>..." to include in what will be committed)
              db/
              file::memory:
      ```
      
      To prevent them from being accidentally committed I put 'file::memory:' to
      `activerecord/db/` folder and added the folder to .gitignore
      Also, we could consider fixing this by removing `db/` folder in each test that
      creates the folder.
      
      It would be great if someone confirms that it happens not only on my VM.
      22877a9d
  5. 29 2月, 2020 1 次提交
    • E
      Fix error in deprecation · 13e28f5f
      eileencodes 提交于
      When I implemented the deprecation for #38536 I left in the setter in
      the initalizer. This meant that objects returned had both `@name` and
      `@spec_name` set and objects looked like this:
      
      ```
      <ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fe0f7100c68
        @env_name="development",
        @name="primary",
        @spec_name="primary",
        @config={
          :adapter=>"mysql2",
          :database=>"recipes_app_development"
        }
      >
      ```
      
      Since we don't use the kwarg to create the hash config and we have the
      reader for reading off the object or selecting from the configurations
      objects list we can remove this so the object looks like:
      
      ```
      <ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fe0f7100c68
        @env_name="development",
        @name="primary",
        @config={
          :adapter=>"mysql2",
          :database=>"recipes_app_development"
        }
      >
      ```
      13e28f5f
  6. 28 2月, 2020 3 次提交
  7. 27 2月, 2020 3 次提交
    • R
      Fix `unscope` when an `eq` node which has no arel attribute · 9698c1bf
      Ryuta Kamizono 提交于
      Current code expect an `eq` node has one arel attribute at least, but an
      `eq` node may have no arel attribute (e.g. `Arel.sql("...").eq(...)`).
      
      In that case `unscope` will raise `NoMethodError`:
      
      ```
      % bundle exec ruby -w -Itest test/cases/relations_test.rb -n test_unscope_with_arel_sql
      Using sqlite3
      Run options: -n test_unscope_with_arel_sql --seed 4477
      
      # Running:
      
      E
      
      Error:
      RelationTest#test_unscope_with_arel_sql:
      NoMethodError: undefined method `name' for #<Arel::Nodes::Quoted:0x00007f9938e55960>
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/where_clause.rb:157:in `block (2 levels) in except_predicates'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/arel.rb:57:in `fetch_attribute'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/where_clause.rb:157:in `block in except_predicates'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/where_clause.rb:156:in `reject'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/where_clause.rb:156:in `except_predicates'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/where_clause.rb:31:in `except'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:487:in `block (2 levels) in unscope!'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:481:in `each'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:481:in `block in unscope!'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:471:in `each'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:471:in `unscope!'
          /Users/kamipo/src/github.com/rails/rails/activerecord/lib/active_record/relation/query_methods.rb:464:in `unscope'
          test/cases/relations_test.rb:2062:in `test_unscope_with_arel_sql'
      ```
      
      We should check for both `value.left` and `value.right` those are arel
      attribute or not.
      9698c1bf
    • E
      Remove unused argument · cadd9661
      eileencodes 提交于
      This was leftover in debugging we did to support `shard` in
      `connected_to`. We don't need this because `with_shard` already has
      access to `connection_specification_name` because they are in the same
      class.
      cadd9661
    • E
      Disallow calling `connected_to` on subclasses of `ActiveRecord::Base` · b7b26fab
      eileencodes 提交于
      Behavior has not changed here but the previous API could be
      misleading to people who thought it would switch connections for only
      that class. `connected_to` switches the context from which we are
      getting connections, not the connections themselves.
      Co-authored-by: NJohn Crepezzi <john.crepezzi@gmail.com>
      b7b26fab
  8. 25 2月, 2020 15 次提交
    • R
      More less and lazy allocation for `assign_attributes` and `_assign_attributes` · 79ba0694
      Ryuta Kamizono 提交于
      https://gist.github.com/kamipo/296b9dd97f690d7960fdfe8de3ca08c7
      
      Before:
      
      ```
      ================================= All symbols ==================================
      
      Warming up --------------------------------------
         assign_attributes     4.425k i/100ms
      Calculating -------------------------------------
         assign_attributes     44.983k (± 2.8%) i/s -    225.675k in   5.020906s
      
      ==================================== Mixed =====================================
      
      Warming up --------------------------------------
         assign_attributes     4.546k i/100ms
      Calculating -------------------------------------
         assign_attributes     46.103k (± 5.2%) i/s -    231.846k in   5.046489s
      
      ================================= All strings ==================================
      
      Warming up --------------------------------------
         assign_attributes     4.511k i/100ms
      Calculating -------------------------------------
         assign_attributes     47.931k (± 7.4%) i/s -    239.083k in   5.023971s
      ```
      
      After:
      
      ```
      ================================= All symbols ==================================
      
      Warming up --------------------------------------
         assign_attributes     4.831k i/100ms
      Calculating -------------------------------------
         assign_attributes     48.206k (± 8.5%) i/s -    241.550k in   5.058372s
      
      ==================================== Mixed =====================================
      
      Warming up --------------------------------------
         assign_attributes     4.960k i/100ms
      Calculating -------------------------------------
         assign_attributes     50.628k (± 3.5%) i/s -    252.960k in   5.002779s
      
      ================================= All strings ==================================
      
      Warming up --------------------------------------
         assign_attributes     5.006k i/100ms
      Calculating -------------------------------------
         assign_attributes     52.242k (± 5.5%) i/s -    260.312k in   5.001695s
      ```
      79ba0694
    • R
    • R
      Remove duplicate part from deprecation warning · 63316b7b
      Ryuta Kamizono 提交于
      Before:
      
      ```
      DEPRECATION WARNING: spec_name is deprecated and will be removed from Rails 6.2 (spec_name accessors are deprecated and will be removed in Rails 6.2, please use name instead.)
      ```
      
      After:
      
      ```
      DEPRECATION WARNING: spec_name is deprecated and will be removed from Rails 6.2 (please use name instead)
      ```
      
      Follow up of #38536.
      63316b7b
    • R
    • R
      Fixup CHANGELOGs [ci skip] · 1d3eb7be
      Ryuta Kamizono 提交于
      1d3eb7be
    • R
      8a72d42b
    • A
      Remove hash deconstruction · eb2aedb5
      Aaron Patterson 提交于
      I don't think this hash deconstruction buys us much in terms of
      readability.  We only need two parameters, the rest are ignored, and on
      top of that we have to allocate a hash.  Convert to positional
      parameters instead.
      eb2aedb5
    • A
      Eliminate a hash allocation when rendering templates · 6878c505
      Aaron Patterson 提交于
      The `**options` in this code allocates a hash.  Most template renders
      are probably not cached, so if we return a little early, we can save a
      hash allocation on each render call.
      
      Here is an allocation benchmark:
      
      ```ruby
      
      require "active_record"
      require "active_record/railties/collection_cache_association_loading"
      require "action_controller"
      require "action_view"
      require "tmpdir"
      
      ActionView::PartialRenderer.prepend(ActiveRecord::Railties::CollectionCacheAssociationLoading)
      
      class TestController < ActionController::Base
        def _prefixes; []; end # Search the current directory rather than "test/"
      end
      
      Dir.mktmpdir do |dir|
        TestController.view_paths = dir
      
        File.write File.join(dir, "_thing.html.erb"), "Hello <%= yield %>"
      
        cv = TestController.new.view_context
      
        # heat
        cv.render("thing") { "World" }
        # delete the line below and allocations go *way* down
      
        def recurse(cv, depth)
          if depth == 0
            cv.render("thing") { "World" }
          else
            cv.render("thing") { recurse(cv, depth - 1) }
          end
        end
      
        def allocs
          x = GC.stat(:total_allocated_objects)
          yield
          GC.stat(:total_allocated_objects) - x
        end
      
        10.times do |i|
          p i => allocs { recurse(cv, i) }
        end
      end
      ```
      
      Before:
      
      ```
      $ be ruby thing.rb
      {0=>58}
      {1=>77}
      {2=>115}
      {3=>153}
      {4=>192}
      {5=>231}
      {6=>270}
      {7=>309}
      {8=>348}
      {9=>387}
      ```
      
      After:
      
      ```
      $ be ruby thing.rb
      {0=>55}
      {1=>73}
      {2=>109}
      {3=>145}
      {4=>182}
      {5=>219}
      {6=>256}
      {7=>293}
      {8=>330}
      {9=>367}
      ```
      
      I realize this is a "micro bench", but we're seeing the same line pop up
      in benchmarks from our app.  I extracted this micro-bench from one we're
      using to test renders inside our app.
      6878c505
    • K
      Support gzip for schema cache · ffc3af63
      Katrina Owen 提交于
      This adds gzip support for both the YAML and the Marshal serialization
      strategies.
      
      Particularly large schema caches can become a problem when deploying to
      Kubernetes, as there is currently a 1*1024*1024 byte limit for the
      ConfigMap. For large databases, the schema cache can exceed this limit.
      ffc3af63
    • K
      Tweak check for schema cache serialization strategy · 41856146
      Katrina Owen 提交于
      This checks for the inclusion of .dump rather than ending
      with dump for the schema cache filename, in order to switch
      between Marshal (.dump) and YAML (default).
      
      This is so that we can wrap gzipping around both strategies
      cleanly.
      41856146
    • K
      Use tempfile when writing schema cache · e10019ea
      Katrina Owen 提交于
      This avoids situations where the schema cache is read by
      another process when the file is only partially written,
      by first writing to a tempfile, and then renaming at the
      end.
      e10019ea
    • K
      Normalize resetting schema cache version for YAML and Marshal · 7febae4e
      Katrina Owen 提交于
      When dumping the schema cache, we first call clear! which resets
      everything, including setting the @version to nil.
      
      Dumping with YAML dumps the correct version, but doesn't actually
      update the instance variable.
      
      Dumping with Marshal writes the variable.
      
      This change makes it more consistent between the two strategies.
      Also, for codebases that use an alternate versioning strategy,
      they only need to overwrite reset_version! rather than overwriting
      the serialization method.
      7febae4e
    • E
      Add support for horizontal sharding · 384e7d13
      eileencodes 提交于
      Applications can now connect to multiple shards and switch between
      their shards in an application. Note that the shard swapping is
      still a manual process as this change does not include an API for
      automatic shard swapping.
      
      Usage:
      
      Given the following configuration:
      
      ```yaml
      production:
        primary:
          database: my_database
        primary_shard_one:
          database: my_database_shard_one
      ```
      
      Connect to multiple shards:
      
      ```ruby
      class ApplicationRecord < ActiveRecord::Base
        self.abstract_class = true
      
        connects_to shards: {
          default: { writing: :primary },
          shard_one: { writing: :primary_shard_one }
        }
      ```
      
      Swap between shards in your controller / model code:
      
      ```ruby
        ActiveRecord::Base.connected_to(shard: :shard_one) do
          # Read from shard one
        end
      ```
      
      The horizontal sharding API also supports read replicas. See
      guides for more details.
      
      This PR also moves some no-doc'd methods into the private namespace as
      they were unnecessarily public. We've updated some error messages and
      documentation.
      Co-authored-by: NJohn Crepezzi <john.crepezzi@gmail.com>
      384e7d13
    • E
      Deprecate `spec_name` and use `name` for configurations · 79ce7d9a
      eileencodes 提交于
      I have so. many. regrets. about using `spec_name` for database
      configurations and now I'm finally putting this mistake to an end.
      
      Back when I started multi-db work I assumed that eventually
      `connection_specification_name` (sometimes called `spec_name`) and
      `spec_name` for configurations would one day be the same thing. After
      2 years I no longer believe they will ever be the same thing.
      
      This PR deprecates `spec_name` on database configurations in favor of
      `name`. It's the same behavior, just a better name, or at least a
      less confusing name.
      
      `connection_specification_name` refers to the parent class name (ie
      ActiveRecord::Base, AnimalsBase, etc) that holds the connection for it's
      models. In some places like ConnectionHandler it shortens this to
      `spec_name`, hence the major confusion.
      
      Recently I've been working with some new folks on database stuff and
      connection management and realize how confusing it was to explain that
      `db_config.spec_name` was not `spec_name` and
      `connection_specification_name`. Worse than that one is a symbole while
      the other is a class name. This was made even more complicated by the
      fact that `ActiveRecord::Base` used `primary` as the
      `connection_specification_name` until #38190.
      
      After spending 2 years with connection management I don't believe that
      we can ever use the symbols from the database configs as a way to
      connect the database without the class name being _somewhere_ because
      a db_config does not know who it's owner class is until it's been
      connected and a model has no idea what db_config belongs to it until
      it's connected. The model is the only way to tie a primary/writer config
      to a replica/reader config. This could change in the future but I don't
      see value in adding a class name to the db_configs before connection or
      telling a model what config belongs to it before connection. That would
      probably break a lot of application assumptions. If we do ever end up in
      that world, we can use name, because tbh `spec_name` and
      `connection_specification_name` were always confusing to me.
      79ce7d9a
    • K
  9. 24 2月, 2020 3 次提交
  10. 23 2月, 2020 1 次提交
  11. 22 2月, 2020 1 次提交
  12. 21 2月, 2020 2 次提交
  13. 20 2月, 2020 2 次提交
  14. 17 2月, 2020 3 次提交
  15. 14 2月, 2020 2 次提交