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)
12日目 DSL
今回はDSLです。DSLというのはドメイン特化言語と呼ばれます。
主に内部DSLについてまとめていきます。
下記のような形でバックアップを取るためのDSLを作りたいとしましょう。
# 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'))
# README #
# 1. backup 'add_your_file_name' #
# 2. backup_timestamp 'add_your_file_name' #
backup_timestamp 'diary2.txt'
実行時にeval
を使っています。
メソッドをトップレベルにベタ書きしているので、また今度リファクタリングしてみようと思います!
バックアップをとりたい時は簡単で、backup
かbackup_timestamp
の後にバックアップを取りたいファイル名を入れればこのDSLを使うことができます。
eval
は読み込んだものすべてをRubyスクリプトとして実行できますので、こういった実行の方法が取れますね。
ちなみにバックアップを取るとこんな感じです。
まとめ
DSLを書くと、ユーザーにとって非常に簡単な形で使えるプログラムが書けます。
ActiveRecord や Rake, Rspecなど様々な形で内部DSLを目にすることができます。
ただ、ちょっとしたタイプミスで動かなくなってしまう設計にしてしまったりすると(今回のもそうなのですが...)痛い目を見てしまうので、設計はちゃんとやりましょう!
あとeval
は用法用量を守ってお使いください!(デバッグとかもやりにくくなります
参照