Ruby自体をそんなに触ったことがなくて、色々詰まるところがあるのでメモ。
ファイル一覧の取得
Dir::glob("./path/to/dir/*).each {|filename|
if !FileTest.directory?(filename)
# do something to the file.
end
}
ファイルパスからファイル名を抽出する
File.basename(filename)
ファイルパスからディレクトリ名を抽出する
File.dirname(filename)
組み込み定数を利用することで、実行時のファイルパスから実行ディレクトリを取得することができる。
runPath = File.expand_path(File.dirname($0))
# or
runPath = File.expand_path(File.dirname(__FILE__))
メソッド末尾の !
?
マーク
どうやら dangerous methods
と呼ばれていて、内部的なステータスが変化するメソッドにつけるという慣例ぽい。
特に中身が変化しないメソッドにつけても大丈夫だった。
(参考: Why are exclamation marks used in Ruby methods?)
コメントで指摘もらいましたが、上記はちょっと解釈が違うらしい。
こっちの内容のほうがそれっぽい?(どちらもシンタックスシュガーとのこと)
What is the purpose of “!” and “?” at the end of method names?
上記のAnswerから引用すると、!
は
Methods ending in ! perform some permanent or potentially dangerous change
ということらしい。
永続的変化、あるいは潜在的に危険な変更を伴う処理の場合につけておくことっぽい?
例えばRailsのActiveRecordの例だと、save
メソッドは失敗したら false
が返るけど、save!
メソッドはエラーを投げるらしい。
また ?
は
Methods ending in ? return a boolean
boolean
が返ることが分かりやすくなってるってことかな?
# こんな感じ?
class Hoge
def initialize(name)
@name = name
end
def method!
@name = "hoge"
end
end
hoge = Hoge.new("aaa")
hoge.method!
代入演算
name=(name)
のように定義するといわゆるSetterを定義できる。
class Hoge
# ... 省略
def name=(name)
print "Input is #{name}"
@name = name
end
end
hoge = Hoge.new("abc")
hoge.name = "efg" # => Input is efg
attr_accessor
で自動定義
どうやらインスタンス変数はそのままでは外部からセットできない?
上記のようにsetterを実装してやる必要があるみたいです。
が、毎回それを書いていくのは大変なので、attr_accessor
というメタクラスのメソッドが用意されています。
コメントで指摘いただきました。
セッターを作るだけなら,attr_accessor でなく attr_writer で OK です。
ゲッターは attr_reader で。
そして,attr_accessor はその両方を作ります。
「アクセサ」なので両方、ということですね。
class Hoge
attr_accessor :age
# ... 略
# セッターだけなら以下
attr_writer :age
# ゲッターだけ
attr_reader :age
end
とすると、name=(name)
を定義したのと同じようなことが自動で定義されます。
メタクラスの拡張
Class
クラスを拡張することで、クラス自体のメソッドを拡張することができます。
JavaScript的にはObjectの拡張に似てます。
class Class
def hoge
print "hoge"
end
end
とすることで、すべてのクラスに hoge
メソッドが追加されます。
Array.hoge # => hoge
クラス・メソッドを定義時に実行させる
# 上記の拡張がなされたとして
class Fuga
hoge # これが実行される
# ... 略
end
ちなみに、そのクラスだけのクラス・メソッドは以下のように定義します。
class Hoge
def self.fuga
end
end
ちなみに定義方法はこれ以外にもいくつかあるようです。
こちらの記事が参考になります→ Ruby のクラスメソッド定義まとめ
※ 当然ですが、Class
の拡張でなくても、継承先のクラスなどで生成時に、継承元クラスのクラス・メソッドを実行させることができます。
ブロックとyield
Rubyを最初に見た時に「お?」と思ったのがこの「ブロック」でした。
↓こういうやつ
3.times {|i|
p i
}
これは、times
に続くブロックを関数と考えると分かりやすいです。
このブロック単位を実行している、というわけです。
そして当然ですが、このブロック変数を受け取るメソッドを自分で定義することも可能です。
実装する際は yield
を使います。
class Hoge
def initialize()
@data = [1, 2, 3, 4, 5]
end
def method
for i in @data
yield(i)
end
end
end
hoge = Hoge.new
hoge.method {|i|
p i
}
# => 1, 2, 3, 4, 5