Twitter の gem を用いた際にツイートのオブジェクトをシリアライズしてそのまま保存する

前提

以下のコードにおいて tweetTwitter::Tweet クラスのオブジェクトであるとします。

結論

tweet に対して to_json メソッドを用います。結果として得られる値は JSON の文字列なので、データベースにそのまま保存できます*1

serialized_tweet_object = tweet.to_json

上記の serialized_tweet_object をオブジェクト(Twitter::Tweet クラスのオブジェクト)に戻すためには 、Twitter::Tweet クラスのオブジェクトを作成する際に、コンストラクタの引数として元々のハッシュを渡せばよいです。

元々のハッシュとは、serialized_tweet_object を JSON からハッシュに変換したものです。一点注意することは、ハッシュのキーはシンボルでなければいけないということです。したがって、JSONJ.parse の引数に symbolize_names: true を付与することを忘れないようにします。

たとえば、以下のようになります。

original_tweet_object = Twitter::Tweet.new(JSON.parse(serialized_tweet_object, symbolize_names: true))

これで、original_tweet_objectTwitter::Tweet クラスの各種 API を用いることができるように復元できました。

背景

なぜツイートのオブジェクトをシリアライズして保存したいのでしょうか。

それはとにもかくにも「Twitter の API には利用に一定の制限があるから」です*2

例えば、実行回数制限があります。なので、ひたすらにツイートを取得するとあっという間に上限に達してしまいます。このことから、「一度取得したデータは無用に再取得したくないので、大切にしておきたい」という動機が生まれてきます。また、過去に遡れるツイートの個数や期限にも制限があります。この制限もまた、同様の動機を生みます。

さらに「シリアライズ」する理由は、「デシリアライズしたオブジェクトを Twitter gem の API を用いて利用したいから」です。例えば、API の戻り値の JSON をデータベースに保存すると Twitter gem の API は(そのままでは)使えません。オブジェクトをデータベースに格納し、オブジェクトとして復元すれば、Twitter gem の API を使うことができ、DRY で冪等な記述が期待できます。

補足

ツイートのオブジェクトだけではなく、ユーザのオブジェクトも同様にして保存することができます。

また、このシリアライズされたデータだけを愚直に生ログのように溜め込むことで、ツイートやユーザの履歴*3を保存することができます。シリアライズされたデータさえ蓄えていれば、あとからどうにでもなります。

Marshal ではだめなのか

Marshal を用いればオブジェクトをそのまま String にできますが、null文字が含まれる String になることがあるため、データベースへの保存ができません。

Twitter::Tweet のドキュメント

*1:JSON型にするかどうかというのは議論があるところです

*2:Twitter API に限ったことではありませんが

*3:特定のツイートのFav数やRT数の履歴だったり、特定のユーザのアイコンの履歴だったり

Powered by はてなブログ