すがブロ

sugamasaoのhatenablogだよ

letとlet!の違いがわからない

違いというか使い分け方がわからない

(追記アリ)

letは使われたタイミングで処理される。let!は毎回処理をされる。
てっきり、letは一回初期化されたら使いまわされるんだと思っていたけど、呼び出されたときは毎回初期化するようだ。

describe 'let_test' do
  let(:sample_1){ puts "****let****"; 'sample1'}
  let!(:sample_2){ puts "****let!****"; 'sample2'}
  before do
    puts "before---"
  end

  after do
    puts "after----"
  end
  it { sample_1.should eq 'sample1'}
  it { sample_1.should eq 'sample1'}
  it { sample_2.should eq 'sample2'}
  it { sample_2.should eq 'sample2'}
end

実行結果はこんな感じ。

%rspec --format doc let_spec.rb

let_test
****let!****
before---
****let****
after----
  should eq "sample1"
****let!****
before---
****let****
after----
  should eq "sample1"
****let!****
before---
after----
  should eq "sample2"
****let!****
before---
after----
  should eq "sample2"

Finished in 0.00204 seconds
4 examples, 0 failures


ちょっと見にくいけど、let及びlet!の{}が呼ばれたタイミングを確認している。letは遅延評価されるみたいなのを読んだことがあったので、一回呼ばれたらキャッシュされる(つまり、sample_1が二回目に呼ばれたときは ****let**** が呼ばれない)と思っていたがそうではなかった。とすると、どちらにせよ使うときには初期化されるのだから使い分ける必要があるのだろうか……というところでよくわからなくなって頭がフットーしそうになった。

The RSpec Book (Professional Ruby Series)

The RSpec Book (Professional Ruby Series)

これに何か書いてありそうなんだけど、ちょっと手元にない*1ので、メモがてら書いておく。あわよくば識者が教えてくれるかもしれないしネ!!(詳しい方、おしえてください><)

教えてもらった

letはキャッシュされるんだけども、その範囲はbefore〜it〜afterの範囲で一回しか初期化されないという意味だそうな。つまり上記のコードではあんまり意味がなかったのだった!

*1:会社におきっぱなし……