Upgrade to Pro — share decks privately, control downloads, hide ads and more …

update_columnsについて無知だった話

Avatar for Tetsu Nishimura Tetsu Nishimura
May 29, 2025
22

 update_columnsについて無知だった話

Avatar for Tetsu Nishimura

Tetsu Nishimura

May 29, 2025
Tweet

Transcript

  1. 概要
 ツクリンクDB
 (PostgreSQL)
 ツクリンクAPP
 Salesforce
 契約情報
 顧客情報など
 契約情報
 顧客情報など
 >

    # DB情報を更新
 > model.update_column(hoge: fuga)
 > 
 > # Salesforceに同期
 > salesforce.sync!(model)
 => 日付情報が同期されていなかった 

  2. 現象再現(コード) 
 > model = Model.find(xxx)
 > target_date = Date.new(2025,

    5, 1)
 > model.update_columns(somedate_at: target_date)
 > # somedate_at: datetime型
 > model.somedate_at
 => nil # 更新されたのにnilになっている
 
 このあとこのデータをつかってSalesforceにも同期をかけている

  3. でもDBには保存されている 
 > model = Model.find(xxx)
 > target_date = Date.new(2025,

    5, 1)
 > model.update_columns(somedate_at: target_date)
 > model.somedate_at
 => nil
 > model.reload.somedate_at
 => Thu, 01 May 2025 00:00:00 JST +09:00 # DBには保存されている

  4. キャストの問題でした 
 ActiveRecord
 - update_columns は ActiveRecord の型変換をスキップしてキャッシュ 
 -

    キャスト済の値としてSQLに突っ込まれる 
 - Date は datetime に自動変換されない 
 - モデル内では型変換に失敗 → nil 扱いされる 
 PostgreSQL
 - update_columnsから型変換されないまま更新リクエストを受ける 
 - 各カラムについてPostgreSQLが型変換して値を更新 
 
 結果
 - ActiveRecordには型変換されない値がキャッシュされる 
 - PostgreSQLには正常に型変換されて書き込まれる 
 

  5. before_type_castは返ってくる 
 > model = Model.find(xxx)
 > target_date = Date.new(2025,

    5, 1)
 > model.update_columns(somedate_at: target_date)
 > model.somedate_at
 => nil
 > model.somedate_at_before_type_cast
 => Thu, 01 May 2025 # キャストしないで読み取ると値が返ってくる
 つまり内部的には値を持っているけど、somedate_at は nil(型変換できなかった)

  6. どんな時に起きる? 
 - update_columns で Date を直接保存
 - saveやupdateでは型変換してキャッシュされる 


    - datetime カラムに対して Time ではない値を入力したとき
 - 読み込み時にActiveRecord がキャストできない値 => nil
 キャッシュ
 ツクリンクAPP
 update_columns
 PostgreSQL
 型変換
 値そのまま

  7. 対処方法 
 > # Timeにしてからupdate_columnsに渡す
 > model.update_columns(
 > somedate_at: target_date.to_time


    > )
 
 # または
 > model.update_columns(
 > somedate_at: Time.zone.local(2025, 5, 1)
 > )