Rubyのunless文で条件式が複数ある場合のメモ
unless文で、条件式が複数ある場合の動作がたまに分からなくなるので、備忘録書いておく。
先に結論を書くと、unless文は if文の条件全体にnotをつける のと同じ。
例
- ball.rb
#!/usr/bin/env ruby # -*- coding: utf-8 -*- class Ball def initialize(color) @color = color end def red_or_blue? if @color == 'red' or @color == 'blue' true else false end end def not_red_and_not_blue? if @color != 'red' and @color != 'blue' true else false end end end
- ball_spec.rb
#!/usr/bin/env ruby # -*- coding: utf-8 -*- require 'rspec' require File.dirname(__FILE__) + '/test' describe "Ball" do context "赤いボール" do subject { Ball.new('red') } it { should be_red_or_blue } it { should_not be_not_red_and_not_blue } end context "青いボール" do subject { Ball.new('red') } it { should be_red_or_blue } it { should_not be_not_red_and_not_blue } end context "黄色のボール" do subject { Ball.new('yellow') } it { should_not be_red_or_blue } it { should be_not_red_and_not_blue } end end
条件A. このボールは青いか、または赤い
red_or_blue? メソッド内の条件式「@color == 'red' or @color == 'blue'」
条件B. このボールは青くもないし赤くもない (条件Aの否定)
not_blue_and_not_red? メソッド内の条件式「@color != 'red' and @color != 'blue'」
ド・モルガンの法則でリファクタリング
not_blue_and_not_red? メソッドの条件式をド・モルガンの法則 で書き換える。
if not (@color == 'red' or @color == 'blue')
unless文でリファクタリング
not_blue_and_not_red? メソッドの条件式をunless文にする。
unless @color == 'red' or @color == 'blue'
結論
unless文の条件式は、条件A.で書いてあるif文の条件式と同じになっている。
おまけ
- 説明用に冗長に書いたけど、本来はif文を書かない。
class Ball def initialize(color) @color = color end def red_or_blue? @color == 'red' or @color == 'blue' end def not_red_and_not_blue? @color != 'red' and @color != 'blue' end end
spec書いてあれば、リファクタリングできる。
- ruby1.9ではロードパスに'.'が含まれていないので、File.dirname(__FILE__)が必要
require File.dirname(__FILE__) + '/test'
requireの前に $LOAD_PATH << '.' でも可
$LOAD_PATH << '.'