Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

小さなActiveSupportモジュールでより良いグローバル

一般的に、グローバル変数は悪いです。ただし、適切な場所にグローバルを配置すると、コードが大幅に簡素化される場合があります。

Railsでは、リクエスト中に1回データを設定できますが、アプリのすべてのレイヤーで使用します。どのユーザーがリクエストを行っていますか?彼らはどのような許可を持っていますか?どのデータベース接続を使用する必要がありますか?

この情報はコード全体で利用できるはずなので、どこにでも渡すのはノイズの集まりになります。ただし、Rubyグローバル変数を使用したり、クラス変数を設定したりすると、独自の問題が発生します。複数のスレッドがそれを上書きする可能性があり、結果的に大きな混乱を招き、回復不能なほど悪いデータになる可能性があります。

グローバルなものが必要ですが、リクエストだけ

プレーンなRubyの方法

通常、これはThread.current[]で処理されます。 。次のようになります:

Thread.current[:current_user] = user

これは簡単です。それはまともな解決策です。ただし、2つの大きな欠点があります。

  1. 誰かが誤ってデータを上書きする可能性があります。

    2人が同じキーを選んだ場合はどうなりますか?あなたはお互いのデータを踏みにじるでしょう。また、ユーザーのようなものを保存している場合、それは深刻な問題になります。自分のアプリでは、これはおそらく問題にはなりません。しかし、宝石を書いている場合、またはRailsアプリが大きくて乱雑な場合は、それについて考える必要があります。

  2. 適切に構成されていません。

    Thread.current[] 単なるデータの大きな袋です。簡単に文書化することはできません。何を取り出すことができるかを知りたい場合は、何を入れるかを検索する必要があります。

    もちろん、これが問題になるほど十分なグローバルデータを片付けている場合は、Thread.current[]よりも心配する必要があります。 の構造の欠如。ただし、それでも覚えておくべきポイントです。

では、Thread.current[]よりも優れたソリューションはありますか ? ご想像のとおり、Rails自体が多くのリクエストローカルデータを管理します。そして、ActiveSupportであるグッズの箱には、従うべき異なるパターンがあります。

レールウェイ

ActiveSupportを掘り下げると、ActiveSupport::PerThreadRegistryに遭遇する可能性があります 。名前から、これがまさに私たちが探しているものであることがわかるでしょう。

ActiveSupport::PerThreadRegistryを使用 、前の例は次のようになります:

class RequestRegistry
  extend ActiveSupport::PerThreadRegistry

  attr_accessor :current_user, :current_permissions
end

RequestRegistry.current_user = user
RequestRegistry.current_user # => user

少し手間がかかります。ただし、ActiveSupport::PerThreadRegistryを使用する :

  • ドキュメントを置く場所があります。 クラスを見ている人なら誰でも、あなたが期待しているグローバルデータと、彼らが使用できるグローバルデータを正確に知ることができます。

  • 見栄えのするAPIを取得します。 実際、クラス変数を設定しているように見えます。スレッドについて心配する必要がなかったとしたら、おそらくそれがあなたのやっていることでしょう。

  • クラスに設定したデータには名前空間が付けられます。 RequestRegistry.current_userについて心配する必要はありません PhoneNumberApiRegistry.current_userとの衝突 、完全に別々に扱われます。

RailsはActiveSupport::PerThreadRegistryを使用します 内部的には、ActiveRecord接続の処理、EXPLAINクエリの保存、ActiveSupport::Notificationsなどに使用します。したがって、PerThreadRegistryの威力のより良い例を探しているなら 、Rails自体は開始するのに最適な場所です。

スレッドとリクエストが一致しない場合

一部のRailsサーバーでは、1つのスレッドが複数のリクエストを処理します。これは、PerThreadRegistryに入れるものすべてを意味します 次のリクエストのために固執します。これはおそらくあなたが望むものではありません。

Railsが行うことを実行し、PerThreadRegistryに入れたものをクリーンアップすることができます。 それらを使い終わった後。そこに何を入れるかによっては、とにかくこれを行う可能性があります。

コメントの中で、MattBはより簡単な解決策であるrequest_storeを指しています。 Thread.current[]のように機能します 、ただし、リクエストごとにクリアされます。

これにより、誰かがPerRequestRegistryを作成できるようにドアが大きく開かれたままになります。 、request_storeの安全性とPerThreadRegistryのAPIを組み合わせたものです 。誰かがすでにこれを行っている場合は、それについて聞いてみたいです!

試してみてください

グローバルデータは悪い場合があります。グローバルが多すぎると、すぐに保守不可能なコードにつながる可能性があります。

ただし、リクエスト全体でデータを中央に保持することが理にかなっている場合は、Thread.current[]を超えてください。 。 ActiveSupport::PerThreadRegistryを指定します またはrequest_storeショット。他に何もないとしても、グローバルデータを扱うリスクは少し低くなります。


  1. ハッカーはハッキングされた Web サイトで何をしますか?

    2017 年はハッカーの年でした。コンテンツ管理システム、電子商取引ポータル、データ侵害から金融機関の Web サイトのハッキングまで、サイバー犯罪は年々増加しています。 2017 年は、Equifax のデータ侵害による大規模な金融データの盗難、2017 年で最も致命的なランサムウェア攻撃であった WannaCry サイバー攻撃、Petya ランサムウェア攻撃、悪名高い yahoo データ侵害など、驚異的なサイバー攻撃が見られました。 ウェブサイトは一般的にどのようにハッキングされますか? Google は最近、ハッキングされた Web サイトの数が 32% 増加したことを明らかにしました

  2. ビッグ データで何が問題になる可能性があるか?

    機械学習とアルゴリズムを中核とするビッグデータは、高い需要と優れた機能により、現在絶頂期にあります。ビッグデータ分析ソリューションを実現するために、いくつかの企業がこの分野の専門知識を求めています。ビッグデータの文化は現在世界を支配しており、企業が予測モデルと統計分析に基づいてビジネス インテリジェンスを達成しようと努力する中で、標準を設定することに成功しています。 データが指数関数的に生成されるにつれて、ビッグデータ、IoT、クラウド コンピューティングなどの最先端技術に対する需要が高まっています。専門家によると、これらのテクノロジーは、今後あらゆるビジネスの必然的な部分になるでしょう。特