LoginSignup
4
4

More than 5 years have passed since last update.

[Ruby] 色々メモ

Last updated at Posted at 2015-11-16

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
4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4