はじめに
Rubyには、標準添付ライブラリというものがあります。これは、Rubyをより便利に活用出来るツールのことです。
これらを活用出来ることで、自分のプログラミングスキルの幅が広がり、メリットしかありませんので、日々の開発のぜひ参考にしてみてください!
ファイル/ディレクトリ操作を極める
Pathname
ファイルパスを表現するクラス。
※Fileクラスと同様のメソッドが使用可能。(こちらの記事を参照)
require 'pathname'
# Pathnameクラスの生成
Pathname.new('/tmp') #=> #<Pathname:/tmp>
Pathname('/tmp') #=> #<Pathname:/tmp>
home = Pathname.new('~')
# 連結する
foo = home.join('foo.txt') #=> #<Pathname:~/foo.txt>
# 部分的なパスを得る
foo.dirname #=> #<Pathname:~>
foo.basename #=> #<Pathname:foo.txt>
foo.expand_path #=> #<Pathname:/Users/tanaka/foo.txt>
foo.expand_path.parent #=> #<Pathname:/Users/tanaka>
foo.expand_path.parent.parent #=> #<Pathname:/Users>
# 文字列に変換する
foo.to_path #=> "~/foo.txt"
foo.to_s #=> "~/foo.txt"
fileutils
ファイル操作を行うための処理を集めたモジュール。
require 'fileutils'
# ファイルを再帰的にコピーする(第1引数にコピー元のファイル、第2引数にコピー先のディレクトリ)
FileUtils.cp_r('src/dir', 'dest/dir')
# コピー元を配列で指定
FileUtils.cp_r(%w(one two three), 'dest/dir')
# ファイル所有者、グループの変更
FileUtils.chown('tanaka', 'staff', 'dir')
FileUtils.chown_R('tanaka', 'staff', 'dir')
# パーミッションの変更
FileUtils.chmod(0700, 'dir')
FileUtils.chmod_R(0700, 'dir')
# ディレクトリの作成
FileUtils.mkdir('foo')
FileUtils.mkdir_p('foo/bar/baz')
# ファイルやディレクトリの移動
FileUtils.mv('foo', 'bar')
# ファイルやディレクトリの削除
FileUtils.rm_r('dir')
# ハードリンクの作成
FileUtils.ln('src', 'dest')
# シンボリックリンクの作成
FileUtils.ln_s('src', 'dest')
FileUtilsのメソッドで使用されるオプション一覧
オプション名 | 意味 |
---|---|
:dereference_root | trueだとシンボリックの指す内容コピー、falseはシンボリック自体コピー |
:force | trueだとStandardErrorを無視する |
:nocreate | trueだとファイルを作成しない |
:noop | trueだと実際の処理を行わない |
:mtime | 最終時刻をTimeか秒数で指定 |
:mode | パーミッションを8進数で指定 |
:preserve | trueだと更新時刻もコピー |
:remove_destination | trueだとコピーを行う前に、コピー先を削除 |
:secure | trueだとファイルの削除にFileUtils.#remove_entry_secureを使用 |
:verbose | trueだと詳細を出力 |
tmpdir
一時的な作業ディレクトリを作成出来ます。
require 'tmpdir'
# 一時ディレクトリの絶対パスを取得
Dir.tmpdir #=> "/var/folders/4h/..."
# 一時ディレクトリを作成してファイルパスを取得
dir = Dir.mktmpdir do |dir|
File.directory?(dir) #=> true
dir #=> "/var/folders/4h/..."
end
# 第1引数にディレクトリ名のプリフィックス、第2引数に親ディレクトリを指定出来る
dir = Dir.mktmpdir('prefix', '/tmp/sample') do |dir|
File.directory? #=> true
dir #=> "/tmp/sample/prefix..."
end
tmpfile
一時ファイルを作成して操作する事ができます。
※Fileクラスと同様のメソッドが使用可能。(こちらの記事を参照)
require 'tmpfile'
# 第1引数にディレクトリ名のプリフィックス、第2引数に親ディレクトリを指定出来る
path = Tempfile.open('prefix', '/tmp/sample') do |f|
f.puts 'foobar'
f.path
end
path #=> "/tmp/sample/..."
File.read(path) #=> "foobar\n"
# Tempfileをopenする
tmpfile = Tempfile.open('prefix', '/tmp/sample') #=> #<File:/tmp/sample/...>
tmpfile.path #=> "/tmp/sample/..."
tmpfile.close
tmpfile.close! # 再オープンできない
特定のフォーマットのテキストデータを扱う
YAML
構造化されたデータをプレーンな文字列で表現するためのデータ形式の1つです。
文字列・整数・浮動小数点・真偽値・nil・配列・ハッシュなどを表現できます!
require 'yaml'
yaml_string = <<EOS
---
remote:
host:localhost
port: 22
ssh: true
username: user
password: null
EOS
# YAMLをオブジェクトとしてロード
p setting = YAML.load(yaml_string) #=> {"remote"=>{"host"=>"localhost", ...}
# 内容の変更
setting['remote'].update(host: 'example.com'
# オブジェクトをYAMLとしてダンプ
p YAML.dump(setting) #=> "---\nremote:\n host: example.com\n ..."
内容をYAMLとしてダンプ
p setting.to_yaml #=> "---\nremote:\n host: example.com\n ..."
JSON
YAML同様、人気のあるデータのダンプ形式の1つです。
こちらは、文字列・整数・浮動小数点・真偽値・nil・ハッシュなどを表現できます!
require 'json'
data = [1, 2.0, {key: 'value'}, nil, true, false]
# JSONをダンプする
json = data.to_json #=> "[1,2.0,{\"key\": \"value\"},null,true,false]"
# ロードする
p JSON.load(json) #=> [1, 2.0, {key: 'value'}, nil, true, false]
# TimeオブジェクトをJSONにダンプ
Time.now.to_json #=> "\"2021-05-14 12:34:56 +0900\""
# RegexpオブジェクトをJSONにダンプ
/ruby[0-9]/.to_json #=> ""\"(?-mix:ruby[0-9])\""
# ObjectオブジェクトをJSONにダンプ
Object.new.to_json #=> "{}"
# RangeオブジェクトをJSONにダンプ
(1..10).to_json #=> "\"1..10\""
# SymbolオブジェクトをJSONにダンプ
:symbol.to_json #=> "\"symbol\""
CSV
コンマと改行で区切ることで表現する形式です。
require 'csv'
# 配列をCSV形式の文字列に変換
['foo', 'bar', 'baz'].to_csv #=> "foo,bar,baz"
# CSV形式の文字列を配列に変換
'foo,bar,baz'.parse_csv #=> ["foo", "bar", "baz"]
# 複数行のCSVをparseする
data = <<EOS
foo,bar,baz
hoge,fuga,hoge
EOS
CSV.parse(data) do |row|
puts row.join('|') #=> "foo|bar|..."
end
# ヘッダを指定する
data = <<EOS
name,age,gender
tanaka,21,man
yoko,32,woman
sato,44,man
EOS
CSV.parse(data, headers: :first_row) do |row|
# ヘッダ名をキーにしてアクセス可能
name = row['name']
age, gender = row.values_at('age', 'gender')
puts "#{name} is #{gender} (#{age})" #=> "tanaka is man (21)", ...
end
# CSVを書き出し
headers = %w(name age gender)
people = [
['tanaka', 21, 'man'],
['yoko', 32, 'woman'],
['sato', 44, 'man']
]
csv_str = CSV.generate('', write_headers: true, headers: headers) {|csv|
people.each do |person|
csv << person
end
}
puts csv_str #=> name,age,gender,\ntanaka,21,man,...
CSV.parseに指定出来るオプション
オプション名 | 意味 |
---|---|
:col_sep | フィールド間のセパレータとして使用する文字列 |
:row_sep | レコード間のセパレータとして使用する文字列 |
:quote_char | シングルクォーとでもフォイールドを囲めるようになる |
:encoding | エンコーディングを指定 |
:unconverted_fields | 変換前の行を配列で得ることができる |
:headers | 1行目をヘッダーとみなす |
:return_headers | ヘッダとみなした1行目もCSVとして読み込む |
:headers_converters | ヘッダ専用のコンバータをProcオブジェクトまたはシンボルを指定 |
:skip_blanks | 空行を飛ばす |
:force_quotes | フィールドの生成時に必ずクォートする |
:write_headers | ヘッダを出力 |
上級者のための文字列オブジェクト
本来IOではない文字列をIOオブジェクトの代わりに用いることができます。
require 'stringio'
def read_upcase(io)
io.read.upcase
end
io = open('|uname')
stringio = StringIO.new('tanaka')
p read_upcase(io) #=> "DARWIN\n"
p read_upcase(stringio) #=> "TANAKA"
集合を扱う
重複の内容そのコレクションを扱うことができるクラスです。
Setを用いることで、集合の比較や要素の追加などを高速で行うことができます。
require 'set'
# Enumerable#to_set
(1..5)..to_set #=> #<Set: {1,2,3,4,5}>
# Set.new
Set[1, 3, 5, 7] #=> #<Set: {1, 3, 5, 7}>
Set.new(%w(tanaka sato suzuki)) #=> #<Set: {"tanaka", "sato", "suzuki"}>
# 長さを返す
set = Set[1, 3, 5, 7]
set.length #=> 3
# 空にする
set = Set[1, 3, 5, 7]
set.clear #=> #<Set: {}>
# 空か確認
set = Set[1, 3, 5, 7]
set.empty? #=> false
# 要素の追加
set = Set[1, 3, 5, 7]
set << 10 #=> #<Set: {1, 3, 5, 7, 10}>
# 要素の削除
set = Set[1, 3, 5, 7, 10]
set.delete(10) #=> #<Set: {1, 3, 5, 7}>
# 要素が存在しなければ追加し、あれば何もしない
set = Set[1, 3, 5, 7]
set.add?(9) #=> #<Set: {1, 3, 5, 7, 9}>
set.add?(1) #=> nil
# 要素が存在すれば削除し、なければ何もしない
set = Set[1, 3, 5, 7]
set.delete(1) #=> #<Set: {3, 5, 7, 9}>
set.delete(100) #=> nil
# Setの連結
set = Set[1, 3, 5, 7]
set.merge(Set[11, 12, 13]) #=> #<Set: {1, 3, 5, 7, 9, 11, 12, 13}>
# 要素をまとめて削除
set = Set[ 1, 3, 5, 7]
set.subtract(1, 3) #=> #<Set: {5, 7}>
# 真となった要素を削除
## 何か削除されれば自信を返す
set = Set[0, 1, 2, 3, 4, 5, 6, 7]
set.reject! {|v| v.zero? } #=> #<Set{1, 2, 3, 4, 5, 6, 7}>
## 常に自身を返す
set.delete_if {|v| v.even? } #=> #<Set{1, 3, 5, 7}>
# 新たな集合を作る
a = %w(a b c).to_set
b = %w(c d e f).to_set
## どちらかに含まれる要素の集合(和集合)
p a | b #=> #<Set: {"a", "b", "c", "d", "e", "f"}>
## 両方に含まれる要素のみ集合(積集合)
p a & b #=> #<Set: {"c"}>
## 片方だけに含まれている集合(対称差)
p a ^ b #=> #<Set: {"a", "b", "d". "e", "f"}>
## aの中でbに含まれない要素の集合(差集合)
p a - b #=> #<Set: {"a", "b"}>
日付と時刻をもっと詳しく!
Time
require 'time'
# 時刻を表す文字列をTimeオブジェクトに変換
time = Time.parse('2021-05-14 12:34') #=> 2021-05-14 12:34:00 +9000
# 各種フォーマットで表現された文字列を返す
time.iso8601 #=> "2021-05-14T12:34:00+09:00"
time.httpdate #=> "Fri, 14 May 2021 03:34:00 GMT"
time.rfc2822 #=> "Fri, 14 May 2021 12:34:00 +0900"
# 第1引数に時刻の文字列、第2引数にフォーマットを指定して、Timeオブジェクトを生成
Time.strptime('2021年5月14日', '%Y年%m月%d日') #=> 2021-05-14 00:00:00 +0900
Date/DateTime
日付を表現するクラス。
require 'date'
# 年月日からDateオブジェクトを得る
date = Date.new(2021, 5, 14)
# 日付を指定した書式の文字列で表現
date.strftime('%Y年%m月%d日') #=> "2021年05月14日"
# 妥当な日付か真偽値で確認
Date.valid_date?(2000, 1, 1) #=> false
# うるう年か真偽値で確認
Date.leap?(2004) #=> true
# 今日の日付を取得
Date.today #=> Fri, 14 May 2021
# 年月日を確認
date.year #=> 2021
date.month #=> 5
date.day #=> 14
# TImeオブジェクトからDateTimeオブジェクトを作成
Time.new.to_date #=> Fri, 14 May 2021
おわりに
いくつかのライブラリを紹介しましたが、かなり便利な機能があったんではないでしょうか?
標準添付ライブラリを味方につけてRubyマスターになりましょう!