CGI#out は標準出力への出力を行いますが、 CGI#header では 出力を行いません。ただ文字列を返すだけです。
そのため
cgi = CGI.new cgi.out({"charset" => "shift_jis"}){ "<html><head><title>TITLE</title></head><body>BODY</body></html>\r\n" }
は正しい例ですが
cgi = CGI.new cgi.header({"charset" => "shift_jis"}) print "<html><head><title>TITLE</title></head><body>BODY</body></html>\r\n"
は間違った例です。