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

RubyonRailsアプリケーションでミックスインとモジュールを使用する方法

モジュールとミックスインは、間違いなく、Rubyを非常に魅力的なものにする優れたリソースです。これらは、他の場所で簡単に使用できるコードをアプリケーションに共有する機能を提供します。また、機能と懸念事項をグループ化することでコードを整理するのに役立ち、コードの可読性と保守性が向上します。

この記事では、モジュールとミックスインの背後にある概念について説明します。モジュールを作成して他のクラスにミックスする方法を学び、RubyonRailsアプリケーションでそれらを使用する利点について説明します。

旅を楽しんでいただければ幸いです!

モジュールとは

モジュールは、名前空間を作成して名前の衝突を防ぐことができ、それらをミックスインとして使用してアプリケーション間でコードを共有できるという2つの大きな利点があるため、Rubyの最も優れたリソースの1つです。

構造的には、モジュールは他のRubyクラスと非常によく似ています。実際、Rubyの場合、Class Moduleです 、以下のirbで確認できます。 コンソール:

> Class.is_a?(Module)
 => true

クラスと同様に、モジュールを使用して、メソッドと定数をグループ化し、コードを共有します。ただし、モジュールとプレーンなRubyクラスにはいくつかの違いがあります。

  • 定義はmoduleから始めます classの代わりにキーワード;
  • モジュールをインスタンス化できないため、モジュールからオブジェクトを作成することはできません。
  • モジュールから継承できないため、代わりにミックスインとして使用します。
  • モジュールはスタンドアロンコードであるため、モジュールの継承階層はありません。

モジュールは、サービス、懸念事項、定数、および同じ責任を持つことで一緒にいなければならないその他のコードを持つのに最適な場所です。

モジュールは次のようになります。

# lib/modules/invoice_creator.rb
module InvoiceCreator
  TAX_FEE = 0.5
 
  def self.generate
    puts "Don't worry! I'll generate the invoice for you at #{TAX_FEE}%"
  end
 
  def invoice_total
    puts "I'll return the invoice total"
    1000
  end
end

この例では、モジュールが2種類のメソッド(モジュールメソッドとインスタンスメソッド)を提供できることを確認できます。

self.generate はモジュールメソッドです。つまり、モジュールを他のオブジェクトに含めたり拡張したりしなくても使用できます。これは、たとえばサービスオブジェクトを作成する場合に非常に一般的です。モジュールメソッドは次のように呼び出すことができます:

2.5.3 :006 > InvoiceCreator.generate
Don't worry! I'll generate the invoice for you
=> nil

invoice_total はインスタンスメソッドであり、それを使用できるようにするには、次のようにモジュールをクラスに含める必要があります。

# app/models/invoice.rb
class Invoice < ApplicationRecord
  include InvoiceCreator # This includes our module in the Invoice class
 
  def calculate_tax
    total = invoice_total # included method from our module
    tax = total * InvoiceCreator::TAX_FEE
    puts "This is the invoice tax: #{tax}"
  end
end

InvoiceCreatorのすべてのインスタンスメソッド Invoiceで利用できるようになります インスタンスなので、calculate_taxを呼び出すことができます 非常に簡単な方法:

2.5.3 :008 > Invoice.new.calculate_tax
"I'll return the invoice total"
"This is the invoice tax: 500.0"
 => nil
2.5.3 :009 >

さらに、calculate_tax内 モジュール内で定義された定数を使用していることに気づきました。前に述べたように、モジュールは優れたコンスタントキーパーです!

ここで、2種類のInvoiceCreatorが必要なシナリオを想像してみてください。 サプライヤーと顧客に対してまったく異なる請求書を生成します。最終的に名前の分類が行われることになりますが、これを回避するために、モジュールの他の大きな利点である名前空間を利用します。次のセクションを見てみましょう。

どこでも名前空間

名前空間は、特定の機能のローカルコンテキストを作成するときにコードを整理する方法として定義できます。これは、先ほど説明したシナリオに必要なものです。顧客の請求書作成者用とサプライヤ用の別のコンテキストです。請求書の作成者。

コードに戻りましょう。 2つの異なるモジュールを作成する必要があります:

# lib/modules/customer/invoice_creator.rb
module Customer
  module InvoiceCreator
    def self.generate
      puts "Don't worry! I'll generate the customer invoice for you"
    end
  end
end
 
# lib/modules/supplier/invoice_creator.rb
module Supplier
  module InvoiceCreator
    def self.generate
      puts "Don't worry! I'll generate the supplier invoice for you"
    end
  end
end

次に、Customer::InvoiceCreatorを使用できます またはSupplier::InvoiceCreator 必要な場所:

2.5.3 :014 > Customer::InvoiceCreator.generate
Don't worry! I'll generate the customer invoice for you
 => nil
2.5.3 :015 > Supplier::InvoiceCreator.generate
Don't worry! I'll generate the supplier invoice for you
 => nil
2.5.3 :016 >

そうすれば、関心の分離の原則を尊重して、特定の各コードが独自のモジュール内にまとめられます。それに加えて、どこにでも名前空間を配置することは、コードを適切に整理するための優れた方法でもあります。

ここで、Rubyモジュールの他の利点であるミックスインをどのように利用できるかを見てみましょう。

ミックスインを使用する魔法

すでにご存知かもしれませんが、Rubyの特徴の1つは、単一の継承メカニズムを実装していることです。つまり、クラスは他の1つのクラスからしか継承できません。多くの場合、より多くのクラスから継承する必要があります。 Rubyでは、継承パターンを介した構成を使用することで、そのニーズに対応できます。

これは、ミックスインを使用して実行できます。別のRubyクラスにコードを混在させると、継承を使用せずにこのクラスにさらに多くの動作を追加することになります。これは驚くべきことです。したがって、Rubyでは、ミックスインは必要なクラスに含めるモジュールです。それにより、コードをクリーンに保ち、責任を分離しておくことで得られます。

たとえば、InvoiceCreator moduleは、InvoiceCalculatorなどの他のいくつかのモジュールによって提供される機能を使用する必要があるサービスです。 、InvoiceRenderer およびInvoiceSender 、請求書作成プロセスを実行するために必要になります。

これは、モジュールのチェーンをミックスインとしてコードに含めることで実現できるため、次の例のようにメソッドを直接使用できます。

# lib/modules/invoice_calculator.rb
module InvoiceCalculator
  def calculate_items_total
    puts "imagine some math here"
  end
end
 
# lib/modules/invoice_renderer.rb
module InvoiceRenderer
  def generate_invoice_pdf
    puts "imagine that we are using some PDF generation magic here"
  end
end
 
# lib/modules/invoice_sender.rb
module InvoiceSender
  def send_invoice
    puts "imagine your favorite mail service being used here"
  end
end

InvoiceCreatorを作成できないため 他の3つのモジュールすべてから継承し、代わりにそれらを含めます。このようにして、InvoiceCreator 他のInvoiceモジュールのすべてのメソッドが含まれており、これらを任意のクラス/モジュールでInvoiceCreatorと呼ぶことができます。 モジュールが含まれます。ただし、注意してください。モジュールのいずれかに同じ名前のメソッドがある場合、それらは互いに上書きします。

# lib/modules/customer/invoice_creator.rb
module Customer
  module InvoiceCreator
    include InvoiceCalculator
    include InvoiceRenderer
    include InvoiceSender
 
    def generate_invoice
      calculate_items_total # from InvoiceCalculator
      generate_invoice_pdf # from InvoiceRenderer
      send_invoice # from InvoiceSender
    end
  end
end

これで、次のようにすることで、サービスメソッドを含める場所ならどこでも呼び出すことができます。

# app/models/invoice.rb
class Invoice < ApplicationRecord
  include Customer::InvoiceCreator
 
  def send_invoice_to_customer
    puts "Don't worry! I'll generate the customer invoice for you"
    generate_invoice
  end
end

これが結果になり、含まれているInvoiceモジュールからInvoiceCreatorを介してメソッドを呼び出します。 モジュール:

2.5.3 :051 > Invoice.new.generate_invoice
Don't worry! I'll generate the supplier invoice for you
imagine some math here
imagine that we are using some PDF generation magic here
imagine your favorite mail service being used here
 => nil

これが、継承の原則よりも合成を使用する方法であることに注意してください。この原則は、可能な限りコンポジションを使用することを好むべきであることを示しています。作曲では、特定の機能を他の人に提供する責任があるクラスを作成します。これはまさに私たちが行っていることです。

これですべてです!

Ruby開発者として、コードの計画、作成、保守、リファクタリングの際に、その機能とシンタックスシュガーを使用するのが大好きです。この記事を通じて、モジュールがコードの可読性を向上させ、1つの責任だけで物事を維持し、コードベースをクリーンで保守しやすいものにするのに役立つ優れたリソースである理由を理解していただければ幸いです。また、複数のソースから継承する必要がある場合は、ミックスインマジックを使用して、コードにモジュールを含めることができます。

ここでは、RubyとRailsの最高のリソースについて話し続けますので、ご期待ください!

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


  1. RubyでStructとOpenStructを使用する方法

    Rubyの構造体とは何ですか? 構造体は組み込みのRubyクラスであり、値オブジェクトを生成する新しいクラスを作成するために使用されます。値オブジェクトは、関連する属性を一緒に格納するために使用されます。 ここに例があります : Point 2つの座標(x &y 。 このデータはさまざまな方法で表すことができます。 いいね : 配列[10, 20] ハッシュ{ x: 10, y: 10 } オブジェクトPoint.new(10, 20) 複数のPointを使用する場合 、オブジェクトアプローチを使用することをお勧めします。 しかし… これら2つの値を一緒に格納するた

  2. RailsアプリケーションでOmniAuth-Twitterを使用する方法

    このチュートリアルでは、アプリケーションのユーザーがTwitterアカウントを使用してログインできるようにする方法を学習します。これを行うには、OAuthなどのツールを使用すると簡単になります。 OmniAuthのTwitter戦略を含むOmniAuth-Twitterを利用します。 飛び込みましょう! はじめに Railsアプリケーションを生成することから始めます。ターミナルから、コマンドを実行して実行します。 rails new Tuts-Social -T Gemfileを開き、ブートストラップgemを追加します。 #Gemfile...gem bootstra