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

Railsの懸念事項:懸念するかどうか

Ruby on Railsを使用したことがある場合は、おそらく懸念事項の概念に出くわしたことでしょう。新しいRailsプロジェクトをジャンプスタートするたびに、ディレクトリ app / controllers / concernsを取得します。 およびapp/ models / concerns 。しかし、何が懸念されますか?そして、なぜRailsコミュニティの人々は時々彼らについてひどく話すのですか?

概要

Rails Concernは、 ActiveSupport ::Concernを拡張するモジュールです。 モジュール。あなたは尋ねるかもしれません—懸念はモジュールとどのように違うのですか?主な違いは、Railsの懸念により、次のように少し魔法をかけることができるということです。

# app/models/concerns/trashable.rb
 
module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end

その単語が含まれているのがわかります。これは、Rubyモジュールに散りばめられたRailsの炭水化物のビットです。 ActiveSupport ::Concernとは 含まれているブロック内に評価したいコードを置くことができます。たとえば、モデルからトラッシングロジックを抽出したいとします。 含まれる 私たちがやったことを実行し、後でそのようにモデルの懸念を含めることができます:

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  # ...
end

この時点ではかなり便利でナイーブですよね?モデルの重量が少し減り、トラッシングは、ソングモデルだけでなく、他のモデル全体で再利用できるようになりました。まあ、物事は複雑になる可能性があります。調べてみましょう。

ミックスインの典型的な例

懸念事項の詳細に着手する前に、それらについて別の説明を追加しましょう。 include SomeModule が表示されたら、 またはextendAnotherModule 、これらはミックスインと呼ばれます。ミックスインは、他のクラスに追加できるコードのセットです。そして、Rubyのドキュメントからわかるように、モジュールはメソッドと定数のコレクションです。したがって、ここで行っているのは、メソッドと定数を含むモジュールをさまざまなクラスに含めて、それらを使用できるようにすることです。

これは、 Trashableで行ったこととまったく同じです。 懸念。モデルオブジェクトをモジュールにトラッシュすることに関する一般的なロジックを抽出しました。このモジュールは、後で他の場所に含めることができます。つまり、ミックスイン はRubyやRailsだけでなく使用されているデザインパターンですが、どこで使用されても、人々はそれが好きで良いと思うか、嫌いで簡単に制御不能になると思います。

これをよりよく理解するために、それらを使用することの長所と短所をいくつか見ていきます。うまくいけば、これを行うことで、懸念事項をいつ使用するか、使用するかどうかを理解することができます。

すべて持っています

Trashable のように、懸念事項を抽出することにした場合 懸念されるのは、 Trashableのすべての機能にアクセスできるようになったことです。 含まれています。これは大きな力をもたらしますが、リチャードシュニーマンがこのトピックに関するブログ投稿で述べたように、「大きな力には複雑なコードを作成する優れた能力があります」。彼は、信頼できるコードを複雑にすることを意味しました。 あなたの懸念にそこにいること。

Trashableを見てみましょう もう一度:

module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end

懸念の論理は、がゴミ箱に入れられたという事実に依存しています 懸念事項が含まれる場合は常にフィールドが存在します。右?大したことではありません、これは私たちが結局望んでいることです。しかし、私が見ているのは、人々がモデルから他のものを懸念に引き込みたくなるということです。これがどのように発生するかを描くために、 Songを想像してみましょう。 モデルには別のメソッドfeatured_authorsがあります :

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end

説明をわかりやすくするために、 Albumを追加しました Trashableも含むモデル 。それでは、曲とアルバムの注目の作者がゴミ箱に入れられたときに通知したいとしましょう。人々はこの論理を次のように懸念の中に入れたくなるでしょう:

module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
 
    notify(featured_authors)
  end
 
  def notify(authors)
    # ...
  end
end

ここで、物事は少し複雑になり始めています。 Songモデルの外部にトラッシングロジックがあるため、 Trashableに通知を入れたくなるかもしれません。 懸念。そこでは、何か「間違った」ことが起こります。 features_authors Songから取得されます モデル。 OK、このパスプルリクエストのレビューとCIチェックを考えてみましょう。

次に、数か月後に、開発者が features_authorsの提示方法を変更する必要があるという新しい要件が設定されます。 歌のために。たとえば、新しい要件では、ヨーロッパの注目の著者のみを表示する必要があります。当然、開発者は、注目の著者が定義されている場所を見つけて編集します。

class Song < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  def featured_authors
    authors.where(featured: true).where(region: 'Europe')
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
 
  has_many :authors
 
  # ...
end

これは、作者をどこに見せてもうまく機能しますが、本番環境にデプロイした後は、世界の他の地域の人々は彼らの曲について通知されなくなります。このような間違いは、懸念事項を使用するときに簡単に発生します。上記の例は単純で人工的なものですが、「野生の」ものは非常に扱いにくい場合があります。

ここで危険なのは、懸念事項(mixin)が、含まれるモデルについて多くのことを知っていることです。これは、いわゆる循環依存です。 。 およびアルバム Trashableに依存 ゴミ箱の場合、ゴミ箱 features_authorsは両方に依存します 意味。 がゴミ箱に入れられたという事実についても同じことが言えます Trashable を使用するには、両方のモデルにフィールドが存在する必要があります 作業に関する懸念。

これが、無関心クラブが反対する可能性がある理由であり、親関心クラブは賛成です。 最初の Trashableのバージョン これは、コードベースで使用するものです。通知を改善して2番目のバージョンを作成する方法を見てみましょう。

どこから来たのか

Trashableを振り返って 通知することで、私たちはそれについて何かをしなければなりません。懸念を使用するときに起こる別のことは、私たちが物事を過度に乾燥させる傾向があるということです。これ):

module Authorable
  has_many :authors
 
  def featured_authors
    authors.where(featured: true)
  end
end

次に、 Song およびアルバム 次のようになります:

class Song < ApplicationRecord
  include Trashable
  include Authorable
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
  include Authorable
 
  # ...
end

すべてを枯渇させましたが、ヨーロッパの注目作家の要件が満たされていません。さらに悪いことに、 Trashable 懸念事項とモデルはAuthorableに依存します 。なんてこったい?少し前に懸念事項を扱っていたときの私の質問です。メソッドがどこから来ているのかを追跡するのは難しいです。

これらすべてに対する私の解決策は、 features_authorsを維持することです。 可能な限りモデルに近づけます。 通知 メソッドはすべきではありません Trashableの一部になる まったく心配。特にモデルが異なるサブグループに通知する傾向がある場合は、各モデルが独自にそれを処理する必要があります。苦痛を軽減する方法を見てみましょう:

 
# Concerns
module Trashable
  extend ActiveSupport::Concern
 
  included do
    scope :existing, -> { where(trashed: false) }
    scope :trashed, -> { where(trashed: true) }
  end
 
  def trash
    update_attribute :trashed, true
  end
end
 
module Authorable
  has_many :authors
 
  # Other useful methods that relate to authors across models.
  # If there are none, ditch the concern.
end
 
# Models
class Song < ApplicationRecord
  include Trashable
  include Authorable
 
  def featured_authors
    authors.where(featured: true).where(region: 'Europe')
  end
 
  # ...
end
 
class Album < ApplicationRecord
  include Trashable
  include Authorable
 
  def featured_authors
    authors.where(featured: true)
  end
 
  # ...
end

このような懸念は管理可能であり、それほど複雑ではありません。 notifyをスキップしました 先に説明した機能は、別の日のトピックになる可能性があるためです。

最後のボス

Railsの作成者であるBasecampにとって、他の懸念事項を参照する懸念事項は、DHHが以前のツイートで示したように完全に問題ないようです:

コードのスクリーンショットを見ると、あなたは畏敬の念を抱いているか、ぞっとしているかのどちらかです。ここには間にはない気がします。このコードを編集する機会があれば、それを「最終的な懸念のボス戦」と想像します。しかし、冗談はさておき、ここで興味深いのは、どの懸念がどちらに依存するかというコメントがあることです。ご覧ください:

  # ...
 
  include Subscribable # Depends on Readable
  include Eventable    # Depends on Recordables
 
  # ...

このようなコメントを付けることは役立つ場合がありますが、特にコードベースを初めて使用する場合は、大雑把なことを行うために設定されています。新しく、コードが持つすべての「落とし穴」に気づいていないと、確かに懸念を下向きのスパイラルに陥れる可能性があります。

このようなものは、DHHがディスカッション内のコメントで共有したものです。内部の応答ツイートは、このコードベースを使用する人々がこのような懸念にどのように対処することになっているのかを尋ねます。 DHHは、多くのドキュメントを作成していないと回答しています。採用することはめったにないため、チームはこれらのドキュメントに精通しています。

しかし、コードベースをよく知っている経験豊富なチームとそれらを使用するための議論を持つことは奇妙で強力ではありません。使うかどうかの方が気持ちいいと思います。モジュールが提供する多重継承に慣れていますか、それとも構成を好みますか?お電話。

結論

これまで見てきたように、懸念事項は、コードを抽出してドライアップするための便利な構文砂糖を提供するモジュールにすぎません。あなたがあなたのベルトの下にもっと便利なツールを持っているなら、多分あなたはすぐに懸念のために手を差し伸べるべきではありません。添付ファイルの処理や例で示したトラッシングロジックなどの動作は、モジュールに抽出するのに適した候補となる可能性があります(懸念事項)。

うまくいけば、一般的な懸念事項やモジュールを扱うときに、考えられる良い点と悪い点を確認できます。完璧なコードはないことを覚えておいてください。そして最後に、試さずに失敗したり成功したりした場合に、自分にとって何が良いのか、何が悪いのかをどのように知ることができますか?

完璧な解決策はありません。ブログ投稿で、Railsが物事を行う方法に関係していることを理解していただければ幸いです。いつものように、あなたの判断を使用し、賛否両論に注意してください。

次の人まで、乾杯!

P.S。 Ruby Magicの投稿をマスコミから離れたらすぐに読みたい場合は、Ruby Magicニュースレターを購読して、投稿を1つも見逃さないでください。


  1. Railsのセキュリティの脅威:インジェクション

    ユーザーデータを扱う場合は、それが安全であることを確認する必要があります。ただし、セキュリティを初めて使用する場合は、扱いにくく、退屈で、複雑に見える可能性があります。 この記事は、一般的なタイプのセキュリティの脆弱性と、それらがRailsの開発にどのように影響するかについて説明するシリーズの最初の記事です。この地形を通るマップとして、OWASPトップ10Webアプリケーションセキュリティリスクを使用します。 OWASPは、 Open Web ApplicationSecurityProjectの略です。 これは、Web上の重大なセキュリティ問題について世界を教育するために働く専門家のグル

  2. Rails5でのAngularの使用

    あなたは前にその話を聞いたことがあります。分散型で完全に機能するバックエンドAPIと、通常のツールセットで作成されたフロントエンドで実行されているアプリケーションがすでにあります。 次に、Angularに移動します。または、AngularをRailsプロジェクトと統合する方法を探しているだけかもしれません。これは、この方法を好むためです。私たちはあなたを責めません。 このようなアプローチを使用すると、両方の世界を活用して、たとえばRailsとAngularのどちらの機能を使用してフォーマットするかを決定できます。 構築するもの 心配する必要はありません。このチュートリアルは、この目的のた