KansaiWorkshop#27 on 2008-06-28

Posted by okkez Wed, 18 Jun 2008 08:10:00 GMT

日本Rubyの会 公式Wiki - 第27回 Ruby/Rails勉強会@関西

もうすぐ開催されます。

今回はかずひこさんも久しぶりに登壇しますので、すごく楽しみです。

お時間のある方は、上記URIに申し込み方法が書いてあるので、そちらを参照の上、参加申し込みしてくださいね。

Posted in | コメントはありません |

るりまに検索機能とかいろいろ付きました

Posted by okkez Thu, 12 Jun 2008 07:52:00 GMT

羊堂本舗 脳ざらし紀行 (2008-06-11)

sheepmanさん++

俺も、1.8.7対応頑張ろう。まだ 1/3 も出来てない。

Ruby reference manual (beta)

Posted in | コメントはありません |

Passenger (mod_rails) を使ってみた

Posted by okkez Tue, 15 Apr 2008 13:58:00 GMT

Overview — Phusion Passenger (a.k.a. mod_rails)

思ったより簡単だったのでちょっとだけ手順を書いておく。

  • Apache は 2.2 系
  • Rails2.0.2
  • Redmine0.7.0RC1

上記はインストールできている and 動作確認できている前提で。 まずは、Passenger をインストール。

sudo gem install passenger

で以下のコマンドを実行。

passenger-install-apache2-module

そうすると対話型っぽい感じになって色々と親切に教えてくれる。足りないライブラリとそれらの入手方法とか。 個人的にはもう少し不親切でもいいような気がした。

このコマンドではApacheのモジュールをビルドするので Windows ではかなり苦労するであろう事が予想される。(調べてないけど)

最後に、httpd.conf に書く設定内容が表示されるのでそれをコピペして Apache を再起動すればOK。 各アプリの設定は後で書く。

もう一つのインストール方法でやる場合は、ソースを展開したディレクトリの下にビルドしてインストールされてしまうので、ちょっと気持ち悪い。手でコピーすればいいけどコマンドが動的に生成されるっぽいのでその辺の調整が必要。

### Redmine を使う

  • /var/webapps/redmine に置いている
  • /var/www/html が Apache の DocumentRoot

サブドメインが使える場合は以下でOK。

ServerName redmine.example.com DocumentRoot /var/webapps/redmine/public

サブドメインが使えない場合(素朴なイントラネットなど)。

ln -s /var/webapps/redmine/public /var/www/html/redmine

のようにシンボリックリンクを DocumentRoot 以下に用意する。 で、以下の内容を httpd.conf を追加する。

DocumentRoot /var/www/html RailsBaseURI /redmine

サブドメインが使える場合は NameBase の VirtualHost でいくらでもアプリケーションを置くことができるが、そうでない場合は以下のようにすればいけるかもしれない。(まだ試してない)

RailsBaseURI /redmine1 RailsBaseURI /redmine2

考えてみたけど VirtualHost を使用せずに一つのアプリに別々のRailsEnv を設置する方法がわからない。 上のやり方だと、一つの環境しか設定できないような気がするし。

以上の設定内容は全部、 Passenger のサイトに書いてあった。最初からドキュメントが揃っているのは素晴らしい!

Posted in | コメントはありません |

第23回Ruby勉強会@関西の初級者レッスン演習問題の解答例たち

Posted by okkez Fri, 22 Feb 2008 15:04:00 GMT

ざっとこんなもんかな。時間ある時に勝手に添削する。

# 添削希望のものだけね。

Kanasan の 100 マス計算

趣味も大分入るけど以下のような感じで添削しました。

  • 題意を勘違いしてる?
    • 演算子もランダムにして欲しかったけどこれはこれでアリなので活かすことにする
  • 使える演算子は決まっているので、定数化する
  • 入力値のチェックに正規表現を使っていたがこの程度なら文字列比較で十分
  • 一度初期化したら変わらない変数は定数にする
  • メソッド定義のカッコは省略しない
    • るりまのフォーマットに従う方向で。
  • exit 1 にしとく
    • コマンドの失敗時の戻り値は 1 であることが多いため
  • 一文字変数はスコープが短い所で使用する
  • 配列の変数名は配列であることが予想できるような名前にする
kanasan's 100マス計算添削後
#! /usr/bin/ruby OPERATORS = %w[+ - * / %] DIGIT = 2 SEPARATOR = " " VERTICAL_LINE = "|" HORIZONTAL_LINE = "-" CROSS_LINE = "+" operator = ARGV[0].to_s unless OPERATORS.include?(operator) puts "wrong parameter: operator is only +-*/%" exit 1 end def display100Math(xs, ys, operator, display_answer) print SEPARATOR * (DIGIT - operator.size) print operator print SEPARATOR print VERTICAL_LINE xs.to_a.each do |x| print SEPARATOR print SEPARATOR * (DIGIT - x.to_s.size) print x end puts "" print HORIZONTAL_LINE * DIGIT print HORIZONTAL_LINE print CROSS_LINE xs.size.times do print HORIZONTAL_LINE print HORIZONTAL_LINE * DIGIT end puts "" ys.each do |y| print SEPARATOR * (DIGIT - y.to_s.size) print y print SEPARATOR print VERTICAL_LINE if display_answer xs.each do |x| answer = y.send(operator, x) print SEPARATOR print SEPARATOR * (DIGIT - answer.to_s.size) print answer end end puts "" end end xs = (1..9).sort_by{rand} ys = (1..9).sort_by{rand} display100Math(xs, ys, operator, false) puts "" display100Math(xs, ys, operator, true)

やらなかったこと

  • 100マス化
    • 今のは 81 マスしかない
  • 短く簡潔にすること
    • やっちゃうと大改造になるため(元が残らない)

sixeight さんの 100 マス計算

同じく趣味が入るけどこんな感じ。

  • いくつかの変数名/メソッド名を変更した
    • 多分、わかりやすくなった?
  • initialize に仕事積めすぎなので @header を make_question に移動
    • そうするとインスタンス変数である必要がなくなるのでローカル変数にした
  • make_matrix は表作成専用にした

適切に仕事を分割することでよりよくなったはず。

sixeight's 100 マス計算添削後
class Hyakumasu def initialize @op = [:+, :-, :*, :/][rand(4)] @row = (0..9).sort_by{ rand } @col = (0..9).sort_by{ rand } end def make_matrix header = "#{@op} | " + @col.join(' ') + "\n--|" + "---" * @col.length @row.inject(header){|r, v| r + "\n#{v} |" + (block_given? ? yield(v) : '') } end def display puts make_matrix puts puts make_matrix{|v| @row.map {|i| "%3d" %((@op == :/ && i.zero?) ? 0 : v.send(@op, i)) }.join } end end Hyakumasu.new.display

Posted in , | コメントはありません |

第23回 Ruby勉強会@関西に行ってきた

Posted by okkez Sun, 17 Feb 2008 13:56:00 GMT

いつも通りみんなの集合時間より早く行って簡単な打ち合わせ。

日本Rubyの会 公式Wiki - 第23回 Ruby/Rails勉強会@関西

Ruby1.9 の仕様 − Array 関連の新しい機能 by こなみ さん

よくも悪くも講義?って感じだった。 最後の方の内容が面白かっただけに尻切れとんぼっぽくなったのが残念。

純粋関数型言語Ruby(3) 30分でわかるMonad by 氏久(ujihisa)さん

やっぱり 30min ではわからなかった Monad

参加者大半おいてけぼり??

Rails以外のWebアプリケーションフレームワーク」 by yhara さん

merb, capmping, ramaze の紹介。前二つはストヤン経由で聞いてたけど結局試してなくてごめんなさい。

今度、試す。

Rubyのリフレクション by 大林さん

おもしろかった。久しぶりに燃えるセッションだった。 # って自分こんなにリフレクション好きだったっけ?

すごく勉強になった。要復習。

これくらいの濃さのセッションが毎回あるといいのだけど。

Ruby初級者向けレッスン第17回 by okkezさん

自分のセッション。

初級者レッスンと言いつつ、るりまの宣伝乙。 演習問題もリファレンスを見てやってもらう前提だったのでこんなものかと。

演習問題の最後に、使うかもしれないメソッド一覧を載せたのは良かったらしい。Keep

そう言えば、自分が発表する場合の時間の読み方がかなり正確になってきた気がする。

Posted in | コメントはありません |

Date#cweek

Posted by okkez Wed, 23 Jan 2008 13:18:00 GMT

Ruby には暦週を求める Date#cweek というメソッドがあるが、こいつは月曜日スタートで日曜日で終わる。

でも、たまに日曜日から土曜日での暦週が欲しくなることがある。というか今日必要になった。

なので作ってみた。

class Date def myweek if wday == 0 (self + 3).cweek # cweek + 1 でいいかも。。。 else cweek end end end

とりあえず試した範囲では上手く動いてた。

Posted in | コメントはありません |

第 20 回 Ruby 勉強会@関西 初級者レッスン演習課題解答例(RSpec版)

Posted by okkez Sun, 04 Nov 2007 03:22:00 GMT

Test::Unit版 と同じことを RSpec でやってみた。

第 20 回 Ruby 勉強会@関西 に解答例(answer.pdf)がアップされていますがそれの捕捉説明的なものです。前回と同様、配布資料(print.pdf)が手元にある前提で進めます。

Test::Unit 版とは書いた時期が違うので微妙に実装が違っていたりします。

ちなみに RSpec を使って書くのは初めてです。RSpec についてはるびまの記事を参照してください。

なお、stack_spec.rb は、そのとき注目している機能に関係のある部分のみ掲載します。

実装するメソッド

  • empty?
    • スタックが空なら true、そうでなければ false を返す。
  • size
    • スタックのサイズを返す。
  • push(val)
    • 引数の値をスタックの一番上に積む。
  • pop
    • スタックの一番上の値を取り除いて返す。スタックが空の場合は Stack::EmptyStackErrorが発生する。

Step1

  • Stack#empty? のテスト
  • 「新しいスタックの empty? は真」
stack_spec.rb
require 'stack' describe Stack, "when empty" do before do @empty_stack = Stack.new end it "should be empty" do @empty_stack.should be_empty end after do @empty_stack = nil end end

Stack が空のときの動作を記述。

  • spec -c で実行すると色つきで結果が表示される
stack.rb
class Stack def empty? true end end
  • とりあえず Test::Unit 版と同じように Fake it してみた

Step2

  • Stack#push と Stack#pop のテスト
  • 「新しいスタックに 3 を push して pop すると 3 が返る」
stack_spec.rb
describe Stack, "when push 3" do before do @stack = Stack.new @stack.push(3) end it "should pop 3" do @stack.pop.should == 3 end after do @stack = nil end end
  • describe の引数に書いた内容を before のブロックに記述する
  • it 〜 end に実際にチェックしたい内容を記述する
  • after のブロックに後始末の処理を記述する
  • before と after は省略可能
stack.rb
class Stack def empty? true end def push(val) end def pop 3 end end
  • Test::Unit 版と同じように Fake it

Step3

  • Stack#size のテスト
  • 「新しいスタックに 3 を push すると size は 1」
stack_spec.rb
describe Stack, "when push 3" do before do @stack = Stack.new @stack.push(3) end it "should pop 3" do @stack.pop.should == 3 end it "should size 1" do @stack.size.should == 1 end after do @stack = nil end end
  • Step2 と事前準備の内容は同じなので同じ describe ブロック内に it 〜 end を追加する
stack.rb
class Stack def empty? true end def push(val) end def pop 3 end def size 1 end end
  • 実装はひたすら Fake it

Step4

  • Stack#size のテスト (2)
  • 「新しいスタックに 3 を push すると size は 1」
  • 「さらに 5 を push すると size は 2」
stack_spec.rb
describe Stack, "when push 3 and 5" do before do @stack = Stack.new @stack.push(3) @stack.push(5) end it "should size 2" do @stack.size.should == 2 end end
  • 前のステップとは状況が違うので新しい describe ブロックを用意した
stack.rb
class Stack def initialize @size = 0 end def empty? true end def push(val) @size += 1 end def pop 3 end def size @size end end
  • Fake it のままでは通らないので、ちょっとまじめに実装。

Step5

  • Stack#empty? のテスト (2)
  • 「新しいスタックに 3 を push すると empty? は偽」
stack_spec.rb
describe Stack, "when push 3" do before do @stack = Stack.new @stack.push(3) end it "should pop 3" do @stack.pop.should == 3 end it "should size 1" do @stack.size.should == 1 end it "should not be empty" do @stack.should_not be_empty end after do @stack = nil end end
  • 事前準備の状況が Step2, Step3 と同じなので同じ describe に振舞を追加
stack.rb
class Stack def initialize @size = 0 end def empty? size == 0 end def push(val) @size += 1 end def pop 3 end def size @size end end

Step6

  • Stack#pop のテスト (2)
  • 「新しいスタックを pop すると Stack::EmptyStackError が発生する」
stack_spec.rb
describe Stack, "when empty" do before do @empty_stack = Stack.new end it "should be empty" do @empty_stack.should be_empty end it "should raise Stack::EmptyStackError" do lambda{ @empty_stack.pop }.should raise_error Stack::EmptyStackError end after do @empty_stack = nil end end
stack.rb
class Stack class EmptyStackError < StandardError end def initialize @size = 0 end def empty? size == 0 end def push(val) @size += 1 end def pop raise EmptyStackError if empty? 3 end def size @size end end

Step7

  • Stack#pop のテスト (3)
  • 「新しいスタックに 3 を push して 5 を push して pop すると size は 1」
stack_spec.rb
describe Stack, "when push 3 and 5, then pop" do before do @stack = Stack.new @stack.push(3) @stack.push(5) @stack.pop end it "should size 1" do @stack.size.should == 1 end after do @stack = nil end end
stack.rb
class Stack class EmptyStackError < StandardError end def initialize @size = 0 end def empty? size == 0 end def push(val) @size += 1 end def pop raise EmptyStackError if empty? @size -= 1 3 end def size @size end end

Step8

  • Stack#pop のテスト (4)
  • 「新しいスタックに 3 を push して 5 を pushして pop すると 5 が返る」
stack_spec.rb
describe Stack, "when push 3 and 5" do before do @stack = Stack.new @stack.push(3) @stack.push(5) end it "should size 2" do @stack.size.should == 2 end it "should pop 5" do @stack.pop.should == 5 end after do @stack = nil end end
stack.rb
class Stack class EmptyStackError < StandardError end def initialize @size = 0 @stack = [] end def empty? size == 0 end def push(val) @size += 1 @stack.push(val) end def pop raise EmptyStackError if empty? @size -= 1 @stack.pop end def size @size end end

Step9

最後にリファクタリングします。

stack_spec.rb
require 'stack' describe Stack, "when empty" do before do @empty_stack = Stack.new end it "should be empty" do @empty_stack.should be_empty end it "should raise Stack::EmptyStackError" do lambda{ @empty_stack.pop }.should raise_error Stack::EmptyStackError end after do @empty_stack = nil end end describe Stack, "when push 3" do before do @stack = Stack.new @stack.push(3) end it "should pop 3" do @stack.pop.should == 3 end it "should size 1" do @stack.size.should == 1 end it "should not be enpty" do @stack.should_not be_empty end after do @stack = nil end end describe Stack, "when push 3 and 5" do before do @stack = Stack.new @stack.push(3) @stack.push(5) end it "should size 2" do @stack.size.should == 2 end it "should pop 5" do @stack.pop.should == 5 end after do @stack = nil end end describe Stack, "when push 3 and 5, then pop" do before do @stack = Stack.new @stack.push(3) @stack.push(5) @stack.pop end it "should size 1" do @stack.size.should == 1 end after do @stack = nil end end
  • 上記の仕様を満たすように実装コードを書き換えます。
  • 本来はちょっとずつ書き換えるべきですが、最終結果のみ書いておきます
stack.rb
require 'forwardable' class Stack extend Forwardable def_delegators(:@stack, :empty?, :push, :size) def initialize @stack = [] end def pop raise EmptyStackError if empty? @stack.pop end class EmptyStackError < StandardError end end
  • forwardable ライブラリを使用するとメソッドを指定して特定のオブジェクトに委譲できる
  • 使用方法はリファレンスマニュアルを確認してください

Posted in | コメントはありません |

第20回 Ruby 勉強会 @ 関西

Posted by okkez Fri, 02 Nov 2007 11:52:00 GMT

行ってきた。

第 20 回 Ruby 勉強会

内容は置いといて、初級者レッスンの解答例(answer.pdf)に補足説明を入れておく。 資料は上記サイトでダウンロードしてくださいな。

以下では、配布資料(print.pdf)が手元にあることを前提に進めていきます。

実装するメソッド

  • empty?
    • スタックが空なら true、そうでなければ false を返す。
  • size
    • スタックのサイズを返す。
  • push(val)
    • 引数の値をスタックの一番上に積む。
  • pop
    • スタックの一番上の値を取り除いて返す。 スタックが空の場合は Stack::EmptyStackErrorが発生する。

テスト駆動開発版

TDD でやってくのです。

Step1

  • Stack#empty? のテスト
  • 「新しいスタックの empty? は真」

ということなのでまずはテストを書きます。

test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end end
空っぽのテストなので簡単ですね。 * Stack#empty? のテストをしたいのでテストメソッド名は test\_empty? * assert は 第一引数の式が真で無い場合にに失敗する で、実装。普通は失敗してから Fake it するのですが、print.pdfでは既に失敗してるのでここではいきなり成功しときます。
stack.rb
class Stack def empty? true end end
ここでは成功さえすれば良いのでいきなり true を返します。 #### Step2 * Stack#push と Stack#pop のテスト * 「新しいスタックに 3 を push して pop すると 3 が返る」 まずテスト。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end end
* Stack#push と Stack#pop のテストなのでテストメソッド名は test\_push\_and\_pop
stack.rb
class Stack def empty? true end def push(val) end def pop return 3 end end
* Stack#push はテストが通るので、まだ空っぽでいい。 * Stack#pop はテストを通すために 3 を返す。 明らかにテストが不足しているが、まだ書かない。一歩ずつ確実に進んで行く。 #### Step3 * Stack#size のテスト * 「新しいスタックに 3 を push すると size は 1」 なにがなんでもまずテスト。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') end end
* push してから size を確認するのでテストメソッド名は test\_push\_and\_size * まだ一個しか push しない * 二個 push したらどうなる?とかこの段階では考えない。
stack.rb
class Stack def empty? true end def push(val) end def pop return 3 end def size 1 end end
* 3 を push したら size が 1 になればいいのだから Stack#size は 1 を返せばいい * しつこく Fake it * テストを通すことだけ考える。 #### Step4 * Stack#size のテスト (2) * 「新しいスタックに 3 を push すると size は 1」 * 「さらに 5 を push すると size は 2」 とりあえずテストを書いてみる。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') @stack.push(5) assert_equal(2, @stack.size, 'push increments the size.') end end
素直に書けばこうなるはず。 実装コード
stack.rb
class Stack def initialize @size = 0 end def empty? true end def push(val) @size += 1 end def pop return 3 end def size return @size end end
* Fake it では通らなくなったので、マジメに実装。 * 放っておいても今のところ大丈夫な部分は放置。 #### Step5 * Stack#empty? のテスト (2) * 「新しいスタックに 3 を push すると empty? は偽」 いつまでも Stack#empty? が true しか返さないのはまずいので、false を返す場合のテストを書いてみる。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') @stack.push(5) assert_equal(2, @stack.size, 'push increments the size.') end def test_push_and_empty? @stack.push(3) assert_equal(false, @stack.empty?, 'a stack with data is not empty.') end end
で、テストが失敗するのでテストが通るように実装コードを変更します。
stack.rb
class Stack def initialize @size = 0 end def empty? return @size == 0 end def push(val) @size += 1 end def pop return 3 end def size return @size end end
* @size == 0 が true/false のいずれかを返すので return します * 関係ない部分は弄りません #### Step6 * Stack#pop のテスト (2) * 「新しいスタックを pop すると Stack::EmptyStackError が発生する」 誰がなんと言おうがテストコードを先に書きます。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') @stack.push(5) assert_equal(2, @stack.size, 'push increments the size.') end def test_push_and_empty? @stack.push(3) assert_equal(false, @stack.empty?, 'a stack with data is not empty.') end def test_empty_pop assert_raise(Stack::EmptyStackError, 'to pop a empty stack raise an error.') {@stack.pop} end end
* 空のスタックに対して pop するのでテストメソッドは test\_empty\_pop * assert_raise はブロックに例外が発生する可能性のある処理を記述する 実装コード
stack.rb
class Stack class EmptyStackError < StandardError; end def initialize @size = 0 end def empty? return @size == 0 end def push(val) @size += 1 end def pop raise EmptyStackError if empty? return 3 end def size return @size end end
* Stack#pop を修正。 * Stack#empty? が true の場合に例外を発生させる * 関係ない部分は意地でも書き換えない #### Step7 * Stack#pop のテスト (3) * 「新しいスタックに 3 を push して 5 を push して pop すると size は 1」 例によってテストを先に書きましょう。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') @stack.push(5) assert_equal(2, @stack.size, 'push increments the size.') end def test_push_and_empty? @stack.push(3) assert_equal(false, @stack.empty?, 'a stack with data is not empty.') end def test_empty_pop assert_raise(Stack::EmptyStackError, 'to pop a empty stack raise an error.') {@stack.pop} end def test_push_push_pop_and_size @stack.push(3) @stack.push(5) @stack.pop assert_equal(1, @stack.size, 'pop decrements the size.') end end
* テストメソッド名は test\_push\_push\_pop\_and\_size * 特別なことはしていません 実装コード
stack.rb
class Stack class EmptyStackError < StandardError; end def initialize @size = 0 end def empty? return @size == 0 end def push(val) @size += 1 end def pop raise EmptyStackError if empty? @size -= 1 return 3 end def size return @size end end
* 関係ない部分は弄らない、と #### Step8 * Stack#pop のテスト (4) * 「新しいスタックに 3 を push して 5 を pushして pop すると 5 が返る」 そろそろ佳境ですが、テストを先に書きます。
test_stack.rb
require 'stack' require 'test/unit' class TestStack < Test::Unit::TestCase def setup @stack = Stack.new end def test_empty? assert(@stack.empty?, 'a new stack is empty.') end def test_push_and_pop @stack.push(3) assert_equal(3, @stack.pop, 'pop returns the last value.') end def test_push_and_size @stack.push(3) assert_equal(1, @stack.size, 'push increments the size.') @stack.push(5) assert_equal(2, @stack.size, 'push increments the size.') end def test_push_and_empty? @stack.push(3) assert_equal(false, @stack.empty?, 'a stack with data is not empty.') end def test_empty_pop assert_raise(Stack::EmptyStackError, 'to pop a empty stack raise an error.') {@stack.pop} end def test_push_push_pop_and_size @stack.push(3) @stack.push(5) @stack.pop assert_equal(1, @stack.size, 'pop decrements the size.') end def test_push_push_and_pop @stack.push(3) @stack.push(5) assert_equal(5, @stack.pop, 'pop returns the last value.') end end
実装コード
stack.rb
class Stack class EmptyStackError < StandardError; end def initialize @size = 0 @values = Array.new end def empty? return @size == 0 end def push(val) @size += 1 @values[@size - 1] = val end def pop raise EmptyStackError if empty? val = @values[@size - 1] @size -= 1 return val end def size return @size end end
外から見た動作ではスタックぽく動くようになりましたね。 さて、 irb で中身を覗いてみましょう。
irb(main):001:0> load 'stack.rb' => true irb(main):002:0> s = Stack.new => # irb(main):003:0> s.push 1 => 1 irb(main):004:0> s.push 2 => 2 irb(main):005:0> s.push 3 => 3 irb(main):006:0> s.inspect => "#" irb(main):007:0> s.pop => 3 irb(main):008:0> s.pop => 2 irb(main):009:0> s.pop => 1 irb(main):010:0> s.inspect => "#" irb(main):011:0>

@values の中身が Stack#pop しても消えませんね。これはスタックとしては拙いのでリファクタリングしましょう。

というわけで次回に続く。

Posted in | コメントはありません |

Older posts: 1 2