LoginSignup
47

More than 5 years have passed since last update.

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

Last updated at Posted at 2012-09-02

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

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

##使い方 : ダメなほう

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 するまでは別なユーザーはツイートできない」という暗黙の制限が発生している

##参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47