なるようになるブログ

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

rails commit log流し読み(2019/03/06)

2019/03/06分のコミットです。

CHANGELOGにのったコミットは以下の通りです。

activerecord/CHANGELOG.md

activesupport/CHANGELOG.md


Add insert_all to ActiveRecord models (#35077)

Active Recordの修正です。

bulk insert用のinsert_all / insert_all! / upsert_allメソッドを追加しています。

User.insert_all([
  { name: 'a', created_at: Time.current, updated_at: Time.current },
  { name: 'b', created_at: Time.current, updated_at: Time.current },
  { name: 'c', created_at: Time.current, updated_at: Time.current }
])
# => #<ActiveRecord::Result:0x0000562614ba2d78 @columns=["id"], @rows=[[5], [6], [7]], @hash_rows=nil, @column_types={"id"=>#<ActiveModel::Type::Integer:0x0000562614a48db0 @precision=nil, @scale=nil, @limit=8, @range=-9223372036854775808...9223372036854775808>}>

callback、validationは実行されないので、callbackで指定される値は自分で明示的に指定する必要があります。

insert_all!はunique constraintに違反した場合、ActiveRecord::RecordNotUniqueをraiseするようになっています(insert_allは無視)。

User.insert_all([
  { id: 1, name: 'a', created_at: Time.current, updated_at: Time.current },
  { id: 1, name: 'b', created_at: Time.current, updated_at: Time.current },
])
# => INSERT INTO "users"("id","name","created_at","updated_at") VALUES (1, 'a', '2019-03-05 23:10:02.382965', '2019-03-05 23:10:02.382977'), (1, 'b', '2019-03-05 23:10:02.382980', '2019-03-05 23:10:02.382983') ON CONFLICT  DO NOTHING RETURNING "id"

User.insert_all!([
  { id: 1, name: 'a', created_at: Time.current, updated_at: Time.current },
  { id: 1, name: 'b', created_at: Time.current, updated_at: Time.current },
])
# => ActiveRecord::RecordNotUnique (PG::UniqueViolation: ERROR:  重複キーが一意性制約"users_pkey"に違反しています)

upsert_allは名前の通りでUPSERT(PostgreSQL / SQLiteではON CONFLICTMySQLではON DUPLICATE KEY UPDATE)が使用されるようになっています。PostgreSQL及びSQLiteはUPSERTがサポートされているバージョンである必要があります。

また、PostgreSQLの場合はreturningオプションで返すattributesを指定、PostgreSQL / SQLiteunique_byオプションでレコードを照会する時に使用するカラムを指定出来るようになっています。


Ensure clear_cache! clears the prepared statements cache

Active Recordの修正です

adapter毎に行っていたprepared statements cacheのクリア処理を、abstract adapterのclear_cache!で行うよう修正しています。

元々は特定のadapterでのみprepared statementsをサポートしていた為個別に行っていたのですが、現在は全てのadapterでサポートしている為、処理漏れを防ぐためにabstract adapterで行うようにしています。


Added Array#including, Array#excluding, Enumerable#including, Enumerable#excluding

activesupport/lib/active_support/core_ext/array/access.rbactivesupport/lib/active_support/core_ext/enumerable.rbの修正です。

まずcollectionに値を追加する為のArray#includingEnumerable#includingメソッドを追加しています。

[ 1, 2, 3 ].including(4, 5) #=> [ 1, 2, 3, 4, 5 ]

値を追加する際にflattenを呼び出している為、Array#+と少しだけ挙動が違います。

[ 1, 2, 3 ].including([[4, 5]])
# => [1, 2, 3, 4, 5]

[ 1, 2, 3 ] + [[4, 5]]
# => [1, 2, 3, [4, 5]]

次に、Array#without及びEnumerable#withoutArray#excludingEnumerable#excludingにリネームしています。これはincludingと名前を合わせる為との事です。なお、withoutもaliasとして残っており、引き続き使用出来るようになっています。

最後に、Array#excluding及びEnumerable#excludingで値をflattenで展開してから処理するよう修正しています。withoutも同様。

# before
[ 1, 2, 3, 4, 5 ].without([4, 5]) #=> [ 1, 2, 3, 4, 5 ]

# after
[ 1, 2, 3, 4, 5 ].without([4, 5]) #=> [ 1, 2, 3 ]

Enable Performance/ReverseEach cop to avoid newly adding reverse.each

.rubocop.ymlの修正です。

Performance/ReverseEach copを追加しています。


Enable Lint/AmbiguousOperator and Lint/AmbiguousRegexpLiteral cops

.rubocop.ymlの修正です。

Lint/AmbiguousOperatorLint/AmbiguousRegexpLiteral copを追加しています。


[ci skip] Fix typo beacuse -> because

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

beacusebecauseに修正しています。


Allow remove_foreign_key with both to_table and options

ACtive Recordの修正です。

remove_foreign_keyメソッドでto_tableoptionsを一緒に指定出来るよう修正しています。

同じテーブルに複数のforeign keyがある場合に削除対象を明示的に指定出来るようにする(e.g. remove_foreign_key :astronauts, :rockets, column: "myrocket_id")為。