なるようになるブログ

読書感想文かrailsについてかrubyについてか

rails commit log流し読み(2018/08/30)

2018/08/30分のコミットです。

CHANGELOGへの追加はありませんでした。


32% Faster Object#try

activesupport/lib/active_support/core_ext/object/try.rbの修正です。

Object#tryメソッドのリファクタリングです。元々はObject#try!メソッドを呼び出すしていたのですが、Object#try!メソッドを使用するのはやめて、Object#try内で処理を行うよう修正しています。

    def try(*a, &b)
-      try!(*a, &b) if a.empty? || respond_to?(a.first)
+      return unless a.empty? || respond_to?(a.first)
+      if a.empty? && block_given?
+        if b.arity == 0
+          instance_eval(&b)
+        else
+          yield self
+        end
+      else
+        public_send(*a, &b)
+      end

上記処理はObject#try!メソッド内で行っている処理をそのまま持ってきただけなのですが、try!を呼び出す際の*aのsplat処理を取り除けたことでArrayの生成処理を減らす事が出来、結果実行速度も上がっている、とのことです。

ベンチマークは[PR]https://github.com/rails/rails/pull/33747)参照。


Merge pull request #33748 from eileencodes/fix-erb-loading-issue-with-db-yaml

activerecord/lib/active_record/tasks/database_tasks.rbrailties/lib/rails/application/configuration.rbの修正です。

Application::Configuration#load_database_yamlメソッドを削除しています。

複数DBサポートの対応(Part 1 Easy Multi db in Rails: Add basic rake tasks for multi db setup)の延長でdatabase.ymlのパースタイミングが変わり、元々あった、database.ymlの中でRails.applicationの値を参照するテストがエラーになってしまいました(Rails.applicationが評価されるより前にファイルのパースが行われる為の筈)。で、その対応として、database.ymlをYAMLとしてだけパースし、erbの評価は行わない、というメソッド(#load_database_yaml)が追加されました。

が、このアプローチだと、下記のようにdatabase.ymlの中でerbを使って設定の分岐を行っているような場合に問題が発生してしまいました。

test:
  primary:
    <<: *default
    database: multiple_databases_test
  animals:
    <<: *default
    <% if something %> # This will break as it's invalid YML
    database: multiple_databases_test_animals
    migrations_paths: "db/animals_migrate"
    <% end %>

production:
  <% all_shards.each do |shard| %> # This will break as it's invalid YAML
  <%= shard.name %>:
    username: ...
  <% end %>

そのため、やはり最初にdatabase.ymlをロードする際にerbの評価も行うようにするよう修正をし、不要になった#load_database_yamlメソッドのは削除しています。なお、元々問題になっていたテストは、テストの内容を修正し対応しています。


Remove unused argument

railties/test/application/rake/dbs_test.rbの修正です。

db_create_and_dropメソッドから不要になった引数を削除しています。


Remove this conditional

railties/test/application/rake/dbs_test.rbの修正です。

先の処理で削除した引数を参照している箇所があったのを修正しています。参照はされているもの、引数が渡せることは無い為、不要なのは変わらず。


Faster time_value.rb

activemodel/lib/active_model/type/helpers/time_value.rbn修正です。

TimeValue#fast_string_to_timeメソッドのリファクタリングです。

マイクロ秒のパース処理で、文字列をRationalに変換 -> 1_000_000を乗算 -> Integerに変換、という流れで処理を行っていたのを、値が特定のフォーマット(.開始で7桁)の場合、.を削除し直接Integerに変換するよう修正しています。それ以外のフォーマットの場合、変わらず元の処理が使われます。

元の処理だと、値の乗算処理に時間が掛かってしまうため。


Merge pull request #33749 from schneems/schneems/faster-fragment

actionpack/lib/abstract_controller/caching/fragments.rbの修正です。

AbstractController::Caching::Fragments#combined_fragment_cache_keyメソッドでcache keyを生成するのにcompactを使用していたのを、flatten! + compact!を使用するようリファクタリングしています。不要なオブジェクトの生成を避ける為。


20% faster try

activesupport/lib/active_support/core_ext/object/try.rbの修正です。

trytry!メソッドの引数が全てArrayになっていたのを、最初の引数(method_name)を切り出しています。

-     def try(*a, &b)
-       return unless a.empty? || respond_to?(a.first)
-       if a.empty? && block_given?
+     def try(method_name = nil, *args, &b)
+       if method_name.nil? && block_given?

メソッド名以外の引数が無い場合にsplat処理が行われず、不要な配列の生成を抑止出来る為。


Merge pull request #33729 from kddeisz/plural-automatic-inverse

activerecord/lib/active_record/reflection.rbの修正です。

inverse associationsを取得する際に、association名が複数形の場合に正しく取得出来ていなかったのを、複数形の場合でも取得出来るよう修正しています。


Add missing require

activerecord/test/cases/associations/inverse_associations_test.rbの修正です。

テスト内で使用するmodelのrequireが不足していたのを追加しています。


Merge pull request #33757 from bogdanvlviv/follow-up-32937

docの修正です。

Signed / Encrypted cookiesにmetadataを指定出来るよう修正した、Purpose Metadata For Signed And Encrypted Cookiesのフォローアップとして、CHANGELOGのフォーマットの修正、config.action_dispatch.use_cookies_with_metadataについてConfiguring Rails Applications guideに説明を追加、Upgrading Ruby on Railsに説明を追加、を行っています。


Remove extra & self.class.column_names in keys_for_partial_write

activerecord/lib/active_record/attribute_methods/dirty.rbの修正です。

Dirty#keys_for_partial_writeメソッドでcolumn nameの積を取得していたのを削除しています。呼び出し元のPersistence moduleで既に行っている為。


Remove attributes_with_values_for_{create,update} for internal use

activerecord/lib/active_record/attribute_methods.rbactiverecord/lib/active_record/persistence.rbの修正です。

AttributeMethods moduleからattributes_with_values_for_createメソッド及び、attributes_with_values_for_updateメソッドを削除しています。

attributes_with_values_for_updateはもう使われていない為。attributes_with_values_for_createまだ使われていたのですが、一箇所だけだったので、使用している箇所で処理を修正し対応しています。


Do not recompute length

activerecord/lib/active_record/result.rbの修正です。

Result#hash_rowsメソッドで、@rowsに対するイテレーションの中でcolumnの長さを取得していたのを、ループ前に値を取得するよう修正しています。