americandog1993の日記

プログラマー歴半年のメモ

VirtualBox上のCentOS(6.8)で rails server した結果をホストOSのブラウザから見る

ホストOSのブラウザでゲストOSの localhost:3000 どうやって見るのってなってハマった。
解決したのでメモ。

vagrantfileに以下の設定を書き足す。

# config.vm.network "forwarded_port", guest: 80, host: 8080 

の下に

config.vm.network :"forwarded_port", guest: 3000, host: 3000

を挿入。

$ vagrant halt
$ vagrant up

再起動して

$ rails s -b 0.0.0.0

railsアプリのディレクトリでこれを実行。

f:id:americandog1993:20170416012216p:plain

ホストOS Chromeのアドレス欄に入力すると・・・

f:id:americandog1993:20170416012317p:plain

いただきましたありがとうございます。

-b 0.0.0.0 の意味はよくわかってない。
とりあえず今は動くrails環境作るの優先でいきたいのであえて深入りしないことにする。

追記
iptable 設定も関係あるっぽい?
ググりながらいろいろいじってたからどれがどう関係あるのかわからん。
あとで確認して必須っぽかったらまた書き足します。

参考
teratail.com

もし女 六村リオの緊急事態 Ruby解答

paiza.jp

『もし次の常駐先が女子エンジニアばっかりだったら』をやっていたら『六村リオの緊急事態』(Bクラス相当)で4時間くらいひっかかって(いかにも要領の悪そうな長いコードができあがり、しかも動かない)、答えを探した。
もし女に関しては解答のシェアを認められているようだが、PAIZA問題は解答をネットに書くのは厳禁なので注意。

Rubyで挑戦していたのでRubyの解答を探したが、見つからない。
公式ブログにPythonの解答例があったが、Pythonの文法が全くわからず、解読できなかった。
最終的にこちらのPHP解答を参考にした。

blog.mimsys.net

PHP経験はないが、Pythonと比べるとはるかに推測可能だった。
ほとんどパクリというか、Rubyに書き直しただけだが、以下が無事通過したRuby解答。
このブログを書いた方には本当に感謝しかない。

input_lines = gets.split(' ')
cur_arr = input_lines[0].split('/')
path_arr = input_lines[1].split('/')
for path in path_arr
    if path == '..'
        cur_arr.pop
    elsif path == '.'
        #何もしない
    else
        cur_arr.push(path)
    end
end
cur_arr.delete('') #'//'を防ぐ
puts '/' + cur_arr.join('/')

敗因はArray.popメソッドを知らなかったことだろう。
これを知るまで拡張Forで全部取り出して最後だけ削除してまた結合し直すとか意味不明なことをやってしまっていた。
ところで、

cur_arr.delete('') #'//'を防ぐ
puts '/' + cur_arr.join('/')

この最後の2行だが、例えば /home/current という入力値を .split してまた .join でくっつけるような単純な処理で考えると、まず、"/"で区切って "", "home", "current" となる。
1行目はこの頭の "" を消すための.deleteメソッドだ。
このまま .join すると home/current となってしまうので2行目の頭で "/" を加えている。
それなら最初からこう書けばいいのではないかと思える。

puts cur_arr.join('/') #=>/home/current

配列先頭の "" を残すことで、何もしなくても先頭に "/" が挿入される。
これは間違いなく正解である。少なくとも例に出したような入力値の場合は。
しかし、自動採点時に5パターンほど値が入力されるのだが、その中に "/ .." という意地悪な入力がある。
後者の書き方だと、この時に "" を出力してしまい不正解となる(正解は"/")。
先のPHP解答の記事を読んでも、この場合の処理にやや苦心された様子が伺える。

Javascript チェックボックスが未選択のままsubmitを押したら警告が出るようにする

チェックボックスがすべて空だったらsubmitさせたくない時。
まずJS。

function isCheck() {
	var arr_checkBoxes = document.getElementsByClassName("checkBoxes");
	var count = 0;
	for (var i = 0; i < arr_checkBoxes.length; i++) {
		if (arr_checkBoxes[i].checked) {
			count++;
		}
	}
	if (count > 0) {
		return true;
	} else {
		window.alert("項目を1つ以上選択してください。");
		return false;
	}
}

getElementsByClassNameはgetElementsByIdのclass版。
引数のクラス名の要素をまとめて配列で取得する。

チェックボックス要素.checkedで選択されてるかどうかの状態を示す。
選択されてたらtrue、されてなかったらfalseを返す。
trueの時、つまりチェックされてる時にcountに1ずつ足していく。

最後のif文で1つでも選択されてるか0かを見る。
0ならfalse。
ここで例えば

if (count >= 2)

とすると「2つ以上選択してください。」とかできる。

if (count === 0) {
  return false;
} else if (count > 2) {
       return false;
} else {
       return true;
}

で、「2つまで選択できます。(ただし未選択は不可)」もできる。
HTMLと合わせたらこうなる。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<script>
			function isCheck() {
				var arr_checkBoxes = document.getElementsByClassName("checkBoxes");
				var count = 0;
				for (var i = 0; i < arr_checkBoxes.length; i++) {
					if (arr_checkBoxes[i].checked) {
						count++;
					}
				}
				if (count > 0) {
					return true;
				} else {
					window.alert("項目を1つ以上選択してください。");
					return false;
				}
			}
		</script>
	</head>
<body>
	<form>
		<input class="checkBoxes" type="checkbox">会社辞めたい</input><br>
		<input class="checkBoxes" type="checkbox">すごく会社辞めたい</input><br>
		<input class="checkBoxes" type="checkbox">会社辞めた</input><br>
		<input type="submit" value="送信" onClick="return isCheck()" />	
	</form>
</body>
</html>

onClickに注意。というのも、

onClick="return isCheck()"

と、必ずreturnを入れなければいけない。
入れないとfalseの時にクリックが無効にならない。
f:id:americandog1993:20170411215032p:plain
何も選ばなかったらこんな風に出てくる。

参考:
[JavaScript] チェックボックスのチェック状態を取得する
チェックボックスを扱う-JavaScript入門