素振りメモ

帰り際の同僚との会話が混じりながら、メッセージ指向でと考えいたら、なんか変なのになった。
自動販売機との相互作用を確認したいのって、自動販売機の中身の要素のコラボレーションいうより自動販売機を観察している何者かってこと???

class VendingMachine
  def initialize
    @cach_register = CashRegister.new
  end

  def observer(ob)
    @observer = ob
  end

  def set_cash_register(cach_register)
    @cach_register = cach_register
  end

  def insert_billcoin(bill_coin)
    back_cash = @cach_register.add_cash(bill_coin)
    if back_cash
      @observer.receive_refund_billcoins back_cash
    end
    @observer.know_total "#{@cach_register.total}"
  end

  def refund
    @observer.receive_refund_billcoins @cach_register.refund
    @observer.know_total "#{@cach_register.total}"
  end
end

class CashRegister
  def initialize
    @current_cashs = []
  end

  def add_cash(cash)
    if [10.yen, 50.yen, 100.yen, 500.yen, 1000.yen].include?(cash)
      @current_cashs << cash
      return nil
    else
      return cash
    end
  end

  def total
    @current_cashs.map(&:value).reduce(:+) || 0
  end

  def refund
    begin
      return @current_cashs
    ensure
      @current_cashs = []
    end
  end
end

class BillCoin < Struct.new(:value)
end

class Fixnum
  def yen
    BillCoin.new(self)
  end
end

describe VendingMachine do
  let(:__allow_p) {
    d = double('person')
    allow(d).to receive(:know_total)
    d
  }

  let(:person) {
    d = double('person')
    subject.observer(d)
    d
  }

  subject {
    target = VendingMachine.new
    target.observer(__allow_p)
    target
  }

  describe "お金の投入と払い戻しについて" do
    specify "お金の投入すると、合計金額がわかる" do
      [10.yen, 50.yen, 100.yen, 500.yen].each{ |coin| subject.insert_billcoin(coin) }

      expect(person).to receive(:know_total).with('1660円')

      subject.insert_billcoin(1000.yen)
    end

    specify 'お金を投入してから払い戻しでお金を受け取る。合計金額は0円' do
      coins = [10.yen, 50.yen]
      coins.each{ |coin| subject.insert_billcoin(coin) }

      expect(person).to receive(:receive_refund_billcoins).with(coins)
      expect(person).to receive(:know_total).with("0円")

      subject.refund
    end
  end

  describe '扱えないお金について' do
    let(:invalid_billcoins) { [1.yen,  5000.yen, 10000.yen] }

    specify '想定外の投入金額の場合は、加算せず釣り銭を返す。合計金額は0円のまま' do
      invalid_billcoins.each do |c|
        expect(person).to receive(:receive_refund_billcoins).with(c)
        expect(person).to receive(:know_total).with("0円")
      end

      invalid_billcoins.each{ |coin| subject.insert_billcoin(coin) }
    end
  end
end