yujiro's blog

webエンジニアをしています。

Effective Ruby 読書メモ

セッターメソッド

インスタンスメソッド内でセッターメソッドを使う場合はselfをつけないと 単なるローカル変数の定義になってしまう。 ただし、selfを使うのはその場合のみにしよう

class Hoge

  attr_accessor :hoge, :tako

  def initialize
    hoge = 'a' # Hoge.new.hoge => nil
    self.hoge = 'a' # Hoge.new.hoge => a
  end

end

p Hoge.new.hoge

定数参照におけるレキシカルスコープ(スコープ)と 継承階層

Ruby は定数を見つけるために レキシカルスコープと継承階層を利用する

module SuperDumbCrypto
  KEY = "password123"

  class Encrypt
    def initialize (key=KEY)
      # ...
    end
  end
end

上記コードでは KEY という定数と Encryptクラス(定数)が同じスコープ(SuperDumbCrypto)で定義されているため、KEY定数をみつけることができる。

イメージ的には

SuperDumbCrypto
    => KEY定義
    => Encrypt
        => KEY 使用可能

って感じか。 javascript に似てるとおもいます。

var a = 'hoge';
function fuga(){
  console.log(a);
}

↑と同じようなことだと思います

module SuperDumbCrypto
  KEY = "password123"
end

class SuperDumbCrypto::Encrypt
  def initialize (key=KEY) # raises NameError
    # ...
  end
end

こっちはだめ。

SuperDumbCrypto
    => KEY
SuperDumbCrypto::Encrypt
    => KEY 使用エラー

っていうスコープになっているんだと思う。

module SuperDumbCrypto
  KEY = "password123"
end

# <<: qualified-crypto
class SuperDumbCrypto::Encrypt
  def initialize (key=SuperDumbCrypto::KEY)
    # ...
  end
end

上記にすればOK

Hash を使うときは Struct にしたほうがよくないかと考えてみる

Reading = Struct.new(:date, :high, :low) do
  def mean
    (high + low) / 2 
  end
end

Reading クラスを定数のようにあつかう

CSV.foreach(file_name, headers: true) do |row|
  @readings << Reading.new(date: Date.parse(row[2]),
                           high: row[10].to_f,
                            low: row[11].to_f)
end

こうすれば

@readings.first.mean

みたいな感じでメソッドつかえる。これは便利。

続きも頑張って書きます