Edited at

Rubyデザインパターン 12日目 : DSL

More than 3 years have passed since last update.

Rubyデザインパターン学習のために、自分なりに読書の結果をまとめていくことに決めました。第12日目はDSLです。(http://www.amazon.co.jp/gp/product/4894712857/ref=as_li_qf_sp_asin_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4894712857&linkCode=as2&tag=morizyun00-22)

スクリーンショット 2015-07-27 11.25.28.png


 12日目 DSL

今回はDSLです。DSLというのはドメイン特化言語と呼ばれます。

主に内部DSLについてまとめていきます。

下記のような形でバックアップを取るためのDSLを作りたいとしましょう。


backup.pr

#   README   #

Backup your textfile.

# Usage #
# 1. backup 'add_your_file_name' #
# 2. backup_timestamp 'add_your_file_name' #

backup 'diary.txt'
backup_timestamp 'diary2.txt'


こういった形でバックアップの取れるDSLを書いてみましょう!

ちなみに今日のまとめは結構自力でコードを書いているので、つたない所が多いかもしれませんがご了承ください!


require 'fileutils'

class Backup
def initialize(source)
@backup_directory_path = 'backup'
@source = source
@backup_directory_full_path = File.expand_path(@backup_directory_path)
end

def backup
FileUtils.mkdir_p @backup_directory_path
FileUtils.cp(@source, @backup_directory_full_path)
end

def backup_timestamp
FileUtils.mkdir_p @backup_directory_path
file_name_timestamp = @source + fixed_timestamp
FileUtils.copy(@source, file_name_timestamp)
FileUtils.mv(file_name_timestamp, @backup_directory_path)
end

def fixed_timestamp
Time.now.to_s.gsub('-', '').gsub(':', '').gsub(' ','').slice(0..13)
end
end

def backup(dir)
Backup.new(dir).backup
end

def backup_timestamp(dir)
Backup.new(dir).backup_timestamp
end

eval(File.read('backup.txt'))


backup.txt

#   README   #

# 1. backup 'add_your_file_name' #
# 2. backup_timestamp 'add_your_file_name' #

backup_timestamp 'diary2.txt'


実行時にevalを使っています。

メソッドをトップレベルにベタ書きしているので、また今度リファクタリングしてみようと思います!

バックアップをとりたい時は簡単で、backupbackup_timestampの後にバックアップを取りたいファイル名を入れればこのDSLを使うことができます。

evalは読み込んだものすべてをRubyスクリプトとして実行できますので、こういった実行の方法が取れますね。

ちなみにバックアップを取るとこんな感じです。

スクリーンショット 2015-08-07 20.46.21.png


 まとめ

DSLを書くと、ユーザーにとって非常に簡単な形で使えるプログラムが書けます。

ActiveRecord や Rake, Rspecなど様々な形で内部DSLを目にすることができます。

ただ、ちょっとしたタイプミスで動かなくなってしまう設計にしてしまったりすると(今回のもそうなのですが...)痛い目を見てしまうので、設計はちゃんとやりましょう!

あとevalは用法用量を守ってお使いください!(デバッグとかもやりにくくなります


参照

http://gihyo.jp/admin/feature/01/dsl/0002