47
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

Twitter Ruby Gem の非スレッドセーフ API は使うべきではない

//最初から廃止すべきだとおもう。

決して推奨できないコードを多くのエントリで見かけたので指摘のために残しておく。

使い方 : ダメなほう

OAuth の各種認証トークンを準備して

Twitter.configure do |config|
  config.consumer_key = "app_consumer_key"
  config.consumer_secret = "app_consumer_secret"
  config.oauth_token = "user_access_token"
  config.oauth_token_secret = "user_access_token_secret"
end

API を叩きにいく。とりあえず動くことには動く。

Twitter.update("こんにちはこんにちは")

問題点

ユーザーに紐づく API リクエストをグローバルなクラスメソッドから実行しているため

  • 処理のタイミングによって、
    Twitter.configure 実行時のユーザーと
    Twitter.update 実行時のユーザーが異なる可能性がある。
  • つまり上記の例では、ユーザー A のツイートが、
    異なるユーザー B のツイートとして流されるというバグの温床になる。

使い方 : スレッドセーフなほう

ユーザーごとにインスタンスを生成する i/f が用意されている。

@client = Twitter::Client.new(
  :consumer_key => "app_consumer_key",
  :consumer_secret => "app_consumer_secret",
  :oauth_token => "user_access_token",
  :oauth_token_secret => "user_access_token_secret"
)
@client.update("こんにちはこんにちは")

consumer key の設定を切り出したいのなら下記のコードでも大丈夫。

Twitter.configure do |config|
  config.consumer_key = "app_consumer_key"
  config.consumer_secret = "app_consumer_secret"
end
@client = Twitter::Client.new(
  :oauth_token => "user_access_token",
  :oauth_token_secret => "user_access_token_secret"
)
@client.update("こんにちはこんにちは")

まとめ

  • 設計は安全側に倒すべき
    • "X のときは忘れずに Y を実行する" という暗黙の i/f は最初から作るべきではない
      • そもそもそういう i/f は最初から使うべきではない
    • 今回の例ではスレッドセーフ云々に関係なく「configure 後に update するまでは別なユーザーはツイートできない」という暗黙の制限が発生している

参考

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
47
Help us understand the problem. What are the problem?