銀行員からのRailsエンジニア

銀行員からのRailsエンジニア

銀行員から転身したサービス作りが大好きなRailsエンジニアのブログです。個人で開発したサービスをいくつか運営しており、今も新しいサービスを開発しています。転職して日々感じていること、個人開発サービス運営のことなどを等身大で書いていきます。

【Rubyによるデザインパターンまとめ14】DSL(ドメイン特化言語)

コードの品質向上のため、Rubyデザインパターンを解説した名著である Rubyによるデザインパターン で紹介されているデザインパターンを1つずつまとめており、今回が第14弾です。(毎週1つが目標です!)

前回の記事(インタプリタパターンのまとめ)はこちらです。
【Rubyによるデザインパターンまとめ13】インタプリタパターン - 銀行員からのRailsエンジニア

今回は DSLドメイン特化言語 についてまとめました。

Railsのコードで実際に使われている箇所をピックアップして説明しています。
f:id:ysk_pro:20200307105417p:plain

DSLドメイン特化言語)とは

ある特定の問題を解決するために専用の言語を定義するパターンです。

Railsでは、Validations・ActiveRecord・Rake・RSpecなど幅広く使われています。

文章の説明よりも実際のコードを見た方が分かりやすので、以下のコードをご覧ください。

コード

Railsのコードのmodelでよく目にする、以下のようなバリデーションを実装したコードはDSLを活用しています。

class Item < ActiveRecord::Base
  validates :title, length: { maximum: 40 }
end

上記のvalidatesは、Railsのコードの中の以下メソッドを呼び出しています。

def validates(*attributes)
  defaults = attributes.extract_options!.dup
  validations = defaults.slice!(*_validates_default_keys)

  raise ArgumentError, "You need to supply at least one attribute" if attributes.empty?
  raise ArgumentError, "You need to supply at least one validation" if validations.empty?

  defaults[:attributes] = attributes

  validations.each do |key, options|
    key = "#{key.to_s.camelize}Validator"

    begin
      validator = key.include?("::") ? key.constantize : const_get(key)
    rescue NameError
      raise ArgumentError, "Unknown validator: '#{key}'"
    end

    next unless options

    validates_with(validator, defaults.merge(_parse_validates_options(options)))
  end
end

rails/validates.rb at 526dd6472b3f3ab72ecc2538067b6c94f395fa36 · rails/rails · GitHub

バリデーションのために専用の言語/記法(例: validates :title, length: { maximum: 40 } )を作ることによって可読性を上げています。

おわりに

ここまで読んでいただきありがとうございます。

Rubyによるデザインパターン の中では、ファイルバックアップ機能を作成するオリジナルのコードを使って説明されていて分かりやすかったので、ご興味ある方は是非合わせてご覧ください。

Rubyによるデザインパターン

Rubyによるデザインパターン

次回は、メタプログラミングをまとめます。

来週も頑張ります!

(追記)
メタプログラミングについてまとめました!
是非合わせてご覧ください。
ysk-pro.hatenablog.com