【Ruby】miniテストのエラー

FJORD BOOT CAMP(フィヨルドブートキャンプ)の課題で実装しているボーリングスコア計算プログラムのテストでエラーが出たので原因をアウトプットしていきます。


エラー

  • ボーリングスコア計算プログラムのテストを実行すると下記のエラーが出た
bowling_object.rb:68:in `pinfalls': undefined method `split' for nil:NilClass (NoMethodError)

「splitメソッドのクラスがnilのため見つかりません。」と解釈、しかしクラスは定義しているはず...なぜ?と思いつつ起点を調べる

  • テストの起点は下記のコード
from bowling_object_test.rb:3:in `<main>'
  • 上記のコードはrequire してbowling_object.rbを読み込む部分。このときにエラーが発生していることがわかる
require './bowling_object'
  • ちなみにbowling_object.rbのファイルの中身は、こんな感じ
# frozen_string_literal: true

class Game
  ...
end

class Frame
  ...
end

class Shot
  ...
end

puts Game.new(ARGV[0]).calculate_score


原因/改善

  • 上記のコードでは、最後のputs Game.new(ARGV[0]).calculate_scoreがrequireしただけで実行されてしまう。つまりARGVが何もない状態で実行されてしまうため、最終的にエラーが発生してしまう。テストを書く際にrequireしたいことを考えると、puts Game.new(ARGV[0]).calculate_scoreはこのファイル自体をrubyコマンドとして実行したときだけ走って欲しい。そんなときは以下のように書く
if __FILE__ == $PROGRAM_NAME
  puts Game.new(ARGV[0]).calculate_score
end
  • __FILE__:現在のファイルの名前を含むマジック変数。rubyは__FILE__を使用して現在のソースファイル名を保持する

  • $PROGRAM_NAME:変数名の先頭に$を付けると、グローバル変数を示す。変数名には実行中のスクリプトの名前が含まれる。PROGRAM_NAMEは、プログラムの名前を文字列で返す定数


そもそもテストコードはクラスのメソッドをテストするだけなので、ファイルを分けるとエラーは起きないということも学んだ。クラスを使ってコードを書く時は、クラスごとにファイルを分けることが重要!

【Ruby】学んだメソッドをアウトプット

最近Rubyの問題をpaizaラーニングで解き始めたので学んだことをアウトプットしていきます。

chompメソッドで末尾の改行文字を削除

chompは文字列の末尾に改行コードがあった場合に、文字列の末尾の改行コードを削除してくれる

# 標準入力で値を取得する場合
a = gets.to_s
b = gets.to_s.chomp
p a
p b

# =>"Z\n"
# =>"Z"


Array.new(n)で欲しい長さの配列を作成

  • 問題:整数 n と n 個の数 a_1, ..., a_n が改行区切りで与えられる。与えられた a_1, ..., a_n の中で最も大きい数を出力する
    例) 整数nが2の場合、例えば4と7が改行区切りで与えられる。そのうちの大きい数の7を出力する
n = gets.to_i # 整数で値を取得

ary = Array.new(n) # 上記で取得したn個の長さの配列を作成
n.times { |i| ary[i] = gets.to_i } # 作った配列に改行区切りで与えられる数を入れていく。
puts ary.max # 配列に入った数の中で一番大きな数を出力


joinメソッドで文字列を連結

整数 n が与えられるので、n 回、半角スペース区切りで paiza と出力する
例) 整数nが2の場合、「 paiza paiza」と出力する

n = gets.to_i # 整数で値を取得

ary = Array.new(n) # 上記で取得したn個の長さの配列を作成
n.times { |i| ary[i] = "paiza" } # 作った配列にpaizaを入れていく
puts ary.join(' ') # 最後にjoinを使って文字列を連結する


splitを使って文字列を分割

問題:整数 n が与えられ、その後に n 個の整数 a_1, ..., a_n が半角スペース区切りで与えられるので、a_1, ..., a_n をそのままの順番で改行区切りで出力する
例) 整数nが2の場合、例えば1と5が半角スペース区切りで与えられる。それを「1 5」という形で出力する

  • splitメソッドは文字列を分割して配列にするためのメソッド

  • 自分の回答

n = gets.to_i

ary = Array.new 
ary << gets.to_s.split(' ')
puts ary
  • mapを使うと短く書くことができる
n = gets.to_i

a = gets.split(' ').map(&:to_i)
puts a
  • map(&:to_i) は、標準入力から取得した文字列をsplitで分割したのち,全ての要素にto_iメソッドを適用している


sprintfを使って0埋めする

問題:標準出力で3桁までのランダムな値を受け取り、その値を0埋めにして3桁の数字を出す

  • 自分の回答
n = gets.to_s # 文字列として値を受け取る
if n.length == 1 # nが1桁の場合は2つの0を追加
  puts "00#{n}"
elsif n.length == 2 # nが2桁の場合は1つの0を追加
  puts "0#{n}"
else # nが3桁の場合はそのまま出力
  puts "#{n}"
end
  • sprintfを使うと短く書くことができる sprintf は「左寄せ」や、数値の「桁のゼロ埋め」や、「小数点以下の桁指定」など、文字列のフォーマットを指定したいときに便利なメソッド。sprintf( "フォーマット", 戻したい値 )の形式で引数を文字列で返す。
n = gets.to_i # 整数として値を受け取る

puts sprintf('%03d', n) #sprintfで与えられた引数を指定フォーマットの文字列として返す

<<sprintfのフォーマット>>
\r\n :表示を改行させる
%幅d : 整数値を指定の桁数で右詰めにする
%-幅d :整数値を指定の桁数で左詰めにする
%+幅d :整数値を符号付きで表示する
%0幅d : 整数値の余った空白をゼロで埋めする
%幅.小数点以下桁数f :小数点以下の桁数を指定する
%幅s :文字列を右詰めで表示する。
%-幅s :文字列を左詰めで表示します。


もっともっとrubyのスキルを向上させたいので継続していきたい!

【JavaScript】関数を作る

今回は便利な関数をアウトプットしていきます。

関数とは?

  • プログラムの一部をまとめて名前をつけたもの。関数は何度でも呼び出せるので同じ処理を繰り返したい時に便利

関数の書き方

  • 「=>」マークのアローを使って下記のように書く
    let 変数 = () => { 関数で実行する文 };

例1) メールの文面を関数で作る

let createMail = () => {
  console.log( 'ABC社の山田です。' );
  console.log( 'ご請求書をお送りします。' );
} ;

// => 呼び出し
createMail();

例2) メールの文面を引数を受け取る関数で作る

let createMail = (recv) => {
  console.log( recv + '様' );
  console.log( 'ABC社の山田です。' );
  console.log( 'ご請求書をお送りします。' );
} ;

// => 呼び出し
createMail('小林');


// => 小林様
// => ABC社の山田です。
// => ご請求書をお送りします。

例3) メールの文面が長文の場合

let createMail = (recv, bill) => {
  let msg = '${recv}様
ABC社の山田です。
${bill}円のご請求書をお送りします。';
  console.log(msg);
} ;

// => 呼び出し
createMail('小林', 10000);


// 小林様
// => ABC社の山田です。
// => 10000円のご請求書をお送りします。

例4) 戻り値を関数で返す

let addTax = (bill) => {
  return bill * 1.10;
};

console.log(addTax(11000));

例5) オブジェクトを作る
- 複数のデータを入れる入れ物としてオブジェクトを作る。一人分のデータをオブジェクトに入れる

let data = [
{ name:'小林', bill:10000, addTax:true },
{ name:'木村', bill:20000, addTax:true },
];

console.log(data[1]['name']);
console.log(data[1]['bill']);

例6) メールを作る関数を組み立てる

let createMail = (recv, apoTime) => {
  let msg = '${recv}様
ABC社の山田です。
${ bil }円のご請求書をお送りします。';
  console.log(msg);
} ;
// 消費税が10%の場合
let addTax = (bill) => {
  return bill * 1.10;
};

//送付先データ
let data = [
{ name:'小林', bill:10000, addTax:true },
{ name:'木村', bill:20000, addTax:true },
];
// メール実行
for(let rec of data) {  // 変数dataに所属する要素を、新規作成したrecに順次入れる間、以下を繰り返す
  let bill = rec['bill'] //変数recのプロパティ「bill」を、新規作成した変数billに入れる
  if(rec['addTax']){ // もしも変数recのプロパティ「bill」が真なら以下を実行
    bill = addTax(bill); // 変数billを指定して消費税を追加し、変数billに入れる
  }
  createMail(rec['name'], bill); // 変数recのプロパティ「name」と変数billを指定してメールを作成
}

// 小林様
// => ABC社の山田です。
// => 11000円のご請求書をお送りします。

// 木村様
// => ABC社の山田です。
// => 22000円のご請求書をお送りします。

ようやく完成〜。

【JavaScript】繰り返し文を学ぶ

一気に覚えようとせず、毎日少しずつやっていきます。
今回はwhilefor文のアウトプット

while文とは?

  • while文は条件を満たす間繰り返ししてくれる処理。条件はあるが、回数が決まっていない時に向いている
    例) 残高が0になるまで繰り返す
let shikin = 50000; // 資金変数に50000を代入
while( shikin >= 0 ) {  // 資金が0になるまで繰り返す
  conole.log( shikin ); // 資金を表示
  shikin = shikin - 5000; // 変数の資金から5000を引いた結果を変数資金に入れる 
} 

// => 50000 
// => 45000
// => 40000
// => 35000
// .
// .
// .
// => 0

shikin = shikin - 5000は代入演算子を使ってshikin -= 5000と書くことができる

※代入演算子

f:id:yskmtg:20210623235546p:plain
代入演算子

for文とは?

  • 回数が決まった繰り返し処理。繰り返しが始まる前に数値を初期化して、継続条件が真の間繰り返される
    for( 初期化; 継続条件; 最終式 ) { 繰り返したい文 }

例1) 同じ文を10回繰り返す

for( let cnt = 0; cnt < 10; cnt++ )  {
  console.log( 'ハロー!');
} 

// => ハロー!
// => ハロー!
// => ハロー!
// => ハロー!
// .
// .
// .
// => ハロー!

例2) for文で九九の計算

for( let x = 1; x < 10; cnt < 10; x++ )  {
  for( let y = 1; y < 10; y++) {
    console.log( x + 'x' + y + '=' + x * y);
  }
} 

// => 1x1=1
// => 1x2=2
// => 1x3=3
// => 1x4=4
// .
// .
// .
// => 9x8=72
// => 9x9=81

繰り返しを脱出するとき

  • breakで繰り返し文から脱出。continueで繰り返し文の先頭に戻って継続

配列を使う

  • 配列は「[ ]」の中に複数値を入れられる「型」
    例1) let wday = ['月', '火', '水', '木', '金'];
    例2) 配列から順番に要素を1つずつ取り出して繰り返し処理をする
let wday = ['月', '火', '水', '木', '金']; // 変数wdayを作成
for( let day of wdays )  { // 変数wdayに所属する変数dayを作成
  console.log( day + '曜日' );
} 

// => 月曜日
// => 火曜日
// => 水曜日
// => 木曜日
// => 金曜日
  • 配列を使って総当たり表を作成する。同じ組み合わせを作らないようにするのが難しい。。。
let team = [ 'A', 'B', 'C', 'D', 'E' ];
let opps = [ 'A', 'B', 'C', 'D', 'E' ];
for( let t1 of team) { // 変数teamに所属する要素を、新規作成した変数t1に順次入れる間、以下を繰り返す
  opps.shift();  // 変数oppsの先頭要素を削除
  for(let t2 of opps) { // 変数oppsに所属する要素を、新規作成した変数t2に順次入れる間、以下を繰り返す
    console.log( t1 + 'vs' + t2 );
  }
}

// => AvsB
// => AvsC
// => AvsD
// => AvsE
// => BvsC
//.
//.
//.

【JavaScript】基礎を学ぶ

最近、JavaScriptを学びはじめたのでアウトプットしていきます。

JavaScriptとは?

  • Webブラウザ内で動くプログラミング言語
  • ユーザが直接操作するユーザインターフェースを作るために使われる
  • 具体的には、更新されたコンテンツの定期表示や、インタラクティブな地図や、2D/3D グラフィックのアニメーションや、ビデオジュークボックスのスクロールなどJavaScriptが多分使われている
  • ユーザインターフェースを作成するHTMLやCSSと組み合わせて使う。JavaScriptは動的にコンテンツを更新したり、マルチメディアを管理したり、その他多くのことができるスクリプト言語

f:id:yskmtg:20210621093511p:plain


バージョンは?

  • 現在で一番新しいバージョンは、ECMAScript 2021かな?
    source:JavaScript って何?
    JavaScriptNetscape という会社が開発を進めていたが、途中で欧州電子計算機工業会(ECMA: European Computer Manufacturers Association)が標準化を進めるようになった。なので、ECMAScript (ECMA-262)とも呼ばれる

基本的なメソッド

  • 出力
console.log("Hello world!");
# => Hello world!
console.log( 10 * 5 );
# => 50

console.log( 2 * 2.5 );
# => 4.5

console.log( ( 2 + 10 ) * 5 );
# => 60

console.log( 5/ (4 * ( 1- 0.2 ) ) );
# => 1.5624


変数

  • 変数を作るには、letを使う。英語のlet beが由来している。letはES2015のバージョンで追加されたものでES5のバージョンではvarが主流の書き方。ちなみに現在もvarは多くのプログラムで使われている
let text = "Hello world!"
console.log( text );
# => Hello world!
  • 予約語と同じ変数名はつけられないので注意!

f:id:yskmtg:20210621100558p:plain
2020年6月時点での予約語


文字列を数値に変換する

  • promptメソッドで入力した値を数値として計算できるようにする場合、parseIntを使う
let kakaku = prompt( "定価を入力せよ!" );
console.log( parseInt( kakaku ) + 100 );


条件分岐で年齢層を分析するプログラム

  • 条件分岐はif文を使う。比較演算子を使うとより細かく条件分岐ができる

f:id:yskmtg:20210621103206p:plain
比較演算子

  • isNaN関数を使って書いていく。isNaN関数は、渡された値が数値に変換可能ならfalse、変換が不可能ならtrueを返す
let text = prompt( '年齢は?' );
if ( ! isNaN( text ) ) {
# もしも変数textが数値に変換不可が真ならば以下を実行
  let age = parseInt( text );
  if (age < 20 ) {
    console.log( '未成年' );
    if ( age >= 6 && age >= 15 ) {
   # もしも変数ageが数値6以上、かつ変数ageが数値15以下が真なら以下を返す
      console.log( '義務教育' );
    }
  } else if( age < 65 ) {
    console.log( '成人' );
  } else {
    console.log(' 高齢者' );
  }
}

磨穿鉄硯で学んでいきます。

【HTML】フォーム部品を作る

今回は、HTMLのフォームタグを復習したので見返して使えるように簡単な備忘録として残します。

色々なフォーム部品がある。

f:id:yskmtg:20210620104707p:plain
フォームタグ

1行テキストのフォーム

<input type="text">
<input type="text", value="hello"> # value属性で初期値を入れておける。画像の左から2番目


パスワードのフォーム

<input type="password"> # 画像の左から3番目


複数行テキストのフォーム

<textarea name="テスト">ああああ※初期値はここに入力する</textarea> # 画像の一番右


入力例を入れておきたい場合

  • 記入例を入れるには、 placeholderを使う。placeholderは入力をはじめると消えてしまう
    f:id:yskmtg:20210620110325p:plain
    記入例
<input type = "text" placeholder = "yskmtg'sブログ">



フォームにラベルをつける

  • ラベルと入力フォームを紐づける必要がある。下記の「名前」を押しても入力欄で入力できるようになる
    f:id:yskmtg:20210620111321p:plain
    名前入力
<label for = "name">名前</label>
<input type = "text" id = "name"> 
  • 一文で書くこともできる
<label >名前<input type = "text"> </label>


ドロップダウンリストをつける

f:id:yskmtg:20210620112235p:plain

f:id:yskmtg:20210620112309p:plain

<body>
  <label for = "side menu">サイドメニュー</label>
  <select id="side menu">
    <option></option>
    <option>サラダ</option>
    <option>ポテト</option>
    <option>アイスクリーム</option>
    <option>ドリンクバー</option>
  </select>
</body>
  • size属性で表示数を指定できる。selectd属性でデフォルトで選択してある値を決められる。またmultiple属性で複数選択できる

f:id:yskmtg:20210620112842p:plain

<body>
  <label for = "side menu">サイドメニュー</label>
  <select id="side menu" size = "3" multiple>
    <option></option>
    <option selectd>サラダ</option>
    <option>ポテト</option>
    <option>アイスクリーム</option>
    <option>ドリンクバー</option>
  </select>
</body>


チェックボックスをつける

  • チェックボックスのラベルとフォームは紐付けて文字を押しただけでもチェックされるようにする。checked属性で最初にチェックしておく項目を決められる

f:id:yskmtg:20210620114108p:plain

<body>
  <fieldset>
    <legend>サイドメニュー</legend>
    <label><input type = "checkbox" checked>サラダ</label>
    <label><input type = "checkbox">ポテト</label>
    <label><input type = "checkbox">アイスクリーム</label>
    <label><input type = "checkbox">ドリンクバー</label>
  </fieldset>
</body>


ラジオボランをつける

  • 上記の"checkbox"を"radio"に変更する。checked属性で最初にチェックしておく項目を決められる。またname属性を設定するとチェックは1つだけつけられるようになる

f:id:yskmtg:20210620114650p:plain

<body>
  <fieldset>
    <legend>サイドメニュー</legend>
    <label><input type = "radio" name = "side menu" checked>サラダ</label>
    <label><input type = "radio" name = "side menu">ポテト</label>
    <label><input type = "radio" name = "side menu">アイスクリーム</label>
    <label><input type = "radio" name = "side menu">ドリンクバー</label>
  </fieldset>
</body>


  • 他にもtype = "color", type = "date", type = "number", type = "range"などの入力部品がある。ただ古いブラウザだとサポートされていないので注意が必要!


ボタンをつける

  • disabledでボタンを押せない設定にもできる

f:id:yskmtg:20210620120405p:plain

<body>
  <input type = "button" value = "OK">
  <button>OK</button>
  <input type = "button" value = "OK" disabled>
  <button disabled>OK</button>
</body>

【HTML】区切りを表すタグ

HTMLの区切りタグを復習したのでアウトプットをしていきます。

HTMLの区切りを表すタグの種類

  • header: 導入的なコンテンツ

  • fotter: コンテンツの締めくくりとして使われる。著作権情報などが入る

  • nav: ページ内のナビゲーションに使われる。メニューのリンクなど

  • asaide: 本文とは関連性が薄いコンテンツに使われる

  • article: 記事や独立したコンテンツに使われる

  • main: 本文の主要なコンテンツを使う処理

  • section: 汎用的に使えるタグ

人によって文書の解釈方法は色々なので、人によってマークアップした結果が違うことも...。
迷ったらHTML: HyperText Markup Language | MDNをチェック!

例えば、<h1>タグの子要素には<section>タグを使えない!など色々と調べることができる。

あまり考えすぎず、でもわかりやすくタグを使っていけるよう注意したい!