Posted at

ARオブジェクトをURI化する`ActiveJob::Arguments#serialize`が色々と使えそう

More than 1 year has passed since last update.


ActiveJob::Arguments#serializeとは

ActiveJobの引数にActiveRecordオブジェクトのインスタンスを渡すと、それはシリアライズされずに、Global IDというURIに変換されます。

これを実現しているのが、ActiveJob::Arguments#serializeActiveJob::Arguments#deserializeです。

例えば、

user = User.find(5)

SampleJob.perform_later(user)

とした場合、引数のuserは、

serialized_args = ActiveJob::Arguments.serialize([user])

〜〜〜

〜〜〜

args = ActiveJob::Arguments.deserialize(serialized_args)

というような処理を挟むイメージです。

この時、上記のserialized_argsは、

[{"_aj_globalid"=>"gid://project_name/User/5"}]

のように、gid://アプリケーション名/モデル名/idの形式で表現されます。

つまり、ActiveRecordのインスタンスをシリアライズせずに保持できるということです。シリアライズする必要がないので、容量を大きく節約することができます。


serializeをActiveJobの外で使う

最新のActiveJobではActiveJob::Argumentsはプライベートな内部モジュールとなっているため、ActiveJobの外で使うには明示的にrequireする必要があります。

require 'active_job/arguments'

使用用途としては、何らかのメソッドに渡す引数・渡された引数を一時的に保存するのに使えそうです。

例えば、

def store_sample(*args)

key = SecureRandom.hex(12)
serialized_args = ActiveJob::Arguments.serialize(args)
Rails.cache.fetch(key.to_s) { serialized_args }
end

store_sample(User.find(4))

のようにローレベルキャッシュを利用することで、CacheStoreにstore_sampleメソッドに渡したActiveRecord型オブジェクトの引数を一時保存することも可能です(容量の問題を無視すれば、通常の方法でも可能ですが・・・)。


使ってみた

というわけで、ActiveJob::Arguments#serializeの仕組みを利用した簡単なRails pluginを作ってみました。

EastResident/step_render

主な機能としては、部分テンプレート(partial)を遅延読み込みするというようなものです。