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

dry-rbとは?Ruby開発に役立つ注目のGemコレクション徹底解説

新しい面白いgemを試してみたいと思いませんか?

そんな方におすすめしたいのがdry-rbです。これは一般的な問題への解決策を提供するgemのコレクションで、18以上のRuby gemで構成されています。それぞれのgemは組み合わせて使うことも、単体で使うことも可能です。

代表的なgemには以下のようなものがあります

  • dry-initializer
  • dry-struct
  • dry-validations
  • dry-events
  • dry-transaction

この記事では、その中から3つのgemをピックアップして紹介し、dry-rbが持つ可能性の一端を体験していただきます!

dry-structでより堅牢なStructを作る方法

RubyのStructは、Structクラスから生成できるオブジェクトの一種ですが、いくつかの制約があります。

例えば

必須の引数が不足した状態でも、Rubyは何も警告してくれません。

dry-struct gemを使えば、より厳密なstructを作成できます。

具体的には次のように書きます

require 'dry-struct'

module Types
  include Dry::Types.module
end

class Video < Dry::Struct
  attribute :title, Types::String
  attribute :views, Types::Views
  attribute :comments, Types::Array
end

Video.new(title: "abc", views: 10, comments: [])

属性を一つでも忘れると、次のようなエラーが発生します:

[Video.new] :comments is missing in Hash input

あまり親しみやすいエラーメッセージではありませんが、目的はきちんと果たしてくれます。

独自の型を作成し、制約を追加することもできます

module Types
  include Dry::Types.module

  Age = Integer.constrained(gt: 0)
end

「gt」は「greater than(より大きい)」を意味します。

つまりAgeは0より大きい整数でなければなりません。

デフォルト値を持たせることはできるのでしょうか?

はい、できます。次のように書きます

module Types
  include Dry::Types.module

  Name = String.default('')
end

また、通常のRuby structに似た短い記法でDry structを作成することもできます。

Book = Dry::Struct(title: Dry::Types["string"])

Book.new(title: "Computer Science 101")

dry-eventsでオブザーバーパターンを実装する

オブザーバーデザインパターンとは、一つの発信元多数のリスナーへ更新情報を配信するパターンのことです。ニュース速報、株価アラート、グループチャットへの新着メッセージなどが典型例でしょう。

非常に一般的なパターンです。

Rubyには、これを実装するためのObservableモジュールが標準で用意されています。

しかし、dry-eventsももう一つの選択肢となります。

パブリッシャーは次のように作成できます

require 'dry/events/publisher'

class Blog
  include Dry::Events::Publisher[:blog]

  register_event('article.published')
  register_event('article.upated')
end

続いて

任意のクラスが自分自身を登録すれば、イベント発生時に通知を受け取れます。

やり方はこちら

class Reader
  def on_article_published(event)
    puts "New article published: #{event[:title]}"
  end

  def on_article_updated(event)
    puts "Article has been updated: #{event[:title]}"
  end
end

blog   = Blog.new
reader = Reader.new

blog.subscribe(reader)

publishメソッドを使えば、イベントをブロードキャストできます:

blog.publish('article.published', title: 'How to Use The dry-events Gem')

このgemについて注意点を挙げると、存在しないイベントを購読・発行してもエラーなく静かに失敗するという点です。実装時には気をつけましょう。

dry-auto_injectによる依存性注入

そもそも依存関係とは何でしょうか?

依存関係とは、クラスが動作するために必要なもの、例えば他のオブジェクトやクラスのことです。

これらのオブジェクトをクラス内で直接生成することもできますが…

依存性注入(Dependency Injection)を使う方法もあります。

依存性注入とは、必要な依存オブジェクトをクラスの外部から「注入」すること、つまり引数として渡すことを指します。

require 'faraday'

class GitHubAPI
  def initialize(http_client = Faraday.new)
    @http_client = http_client
  end
end

こうすることで依存関係をコントロールでき、テストもしやすくなります。

さらに

dry-auto_injectを使えば、これらのオブジェクトの生成を自動化できます。開発者が行うのは、必要な依存関係を宣言することだけです。

この例では、FruitStoreに依存しています

require 'dry/auto_inject'

class Store
  def bananas
    puts 'Have some organic bananas!'
  end
end

Import = Dry::AutoInject({ 'store' => Store.new })

class Fruit
  include Import['store']

  def eat
    store.bananas
  end
end

fruit = Fruit.new
fruit.eat

まず、オブジェクトがどのように生成されるかを宣言します:

Import = Dry::AutoInject({ 'store' => Store.new })

そして、その依存関係をクラスで利用できるようにします:

include Import['store']

こうすると、異なるStoreを持つFruitを次のように簡単に作成できます:

Fruit.new(store: MyStore.new)

依存性注入はgemなしでも実現できますが、別のアプローチがあるのは知っておいて損ではありません。

まとめ

この記事では、コード内の特定の設計課題を解決するのに役立つ、魅力的なRuby gemのコレクション「dry-rb」について学びました。

ぜひ実際に手を動かして、その使い心地を確かめてみてください!

最後までお読みいただきありがとうございました。

  1. C++のアロー演算子(->)とは?ドット演算子との違いを実例で解説

    C++では、クラスや構造体のメンバーにアクセスする際に、ドット演算子(.)とアロー演算子(->)の2種類を使います。どちらも同じ目的で使用されますが、適用される場面が異なります。C++において、class、struct、unionとして宣言された型はすべて「クラスタイプ」に分類されるため、以下の説明はこれら3つすべてに当てはまります。 )の使い分け a.b の場合 a.b は、b がオブジェクトa(またはオブジェクトへの参照)のメンバーである場合にのみ使用できます。つまり、a.b における a は、常にクラスの実体(オブジェクト本体)か、オブジェクトへの参照でなければなりません。

  2. なぜクラスを作るのか?抽象化の重要性と良いクラス設計の基本

    前回の記事「なぜnilを使うのか」に続き、普段当たり前と思って使っているものについても、同じ問いを立ててみるのは良いアイデアではないでしょうか。 例えば… 巨大で醜いコードの塊を1つ作るのではなく、なぜ私たちはクラスを使うのでしょうか? 基本的なレベルで言えば、コードとデータを論理的な単位に整理するためにクラスを使います。しかし、それだけではありません。 クラスを使うと、抽象化(abstraction)を作り出せるのです。 抽象化とは何か? 実は、私たちは毎日、毎分、抽象化を利用しています。 今この記事を書いているキーボードは、次のようなもので構成されています。 ケーブル Cherry MX