Load to Professional...

AWSエンジニアの日常。地に足をつける。

多重配列付近でNoMethodError for NilClassが出たとき

Webアプリ開発中に、controllerのunit test作成中にNoMethodError for NilClassが出て詰まったためメモ。

 

環境

・コントローラ (session_cotroller)

~略〜
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
if user.admin
redirect_to admin_url
else
redirect_to root_url
end
else
flash.now[:danger] = "invalid email/password, failed to login"
render 'new'
end
end
~略〜
 
上記のコントローラに対して、以下のようなテストを記述した
 
・spec/controllers/sessions_controller_spec.rb
describe "#create" do

context "as correct user" do
let(:user) { FactoryBot.create(:user) }
let(:valid_parameters) do
{ email: user.email, password: user.password }
end

it "success to log in" do
post :create, session: valid_parameters }
expect(session[:user_id]).to eq user.id
end
end
end
 
すると、こんなエラーが。。。。
 

Failure/Error: user = User.find_by(email: params[:session][:email].downcase)

 

 NoMethodError:

 undefined method `[]' for nil:NilClass

 # ./app/controllers/sessions_controller.rb:10:in `create'

 # ./spec/controllers/sessions_controller_spec.rb:33:in `block (4 levels) in <main>'

 


 

エラー文の内容から、params[:session]がnilになってるのかな?とは推測できましたが、その原因がrspec側にあると考えず、controller側の修正を頑張ってしまうという見当違いなことをしてしまった。。。

 

解決策 

調べているうちに、この記事に出会う。

 https://teratail.com/questions/44554

 

上記記事によると、答えは単純明快。

コントローラ側は、

params[:session][:email]

と多重配列で値を渡しているが、

RSpec側は、

sessions[:email]

としてしまい、エラー。

 

paramsに値を入れられていないのだからnilになるのは当然ですよね、って話だった。

 

原因
user = User.find_by(email: params[:session][:email].downcase)

 

 これの意味を理解してかけていなかったことがそもそもの原因

 

教訓

・「理解できるコード」だけ書くようにしろ、を守れ。

・controllerで渡す値とテストで渡す値はANDになってますよね、って確認しよう。

【Javascriptの基本】変数宣言の使い分け 〜var、let、const〜

■はじめに

Javascriptを学びはじめ、最初に疑問に思ったことが、
変数宣言の方法が2種類あること。

「var」 と 「let」 です。
定数を宣言する「const」も含めたら3種類になります。

Javascript(以下:js)学習に利用させていただいている
https://developer.mozilla.org/ja/ さん
では、

コードでは 「var」ではなく可能な限り「let」 を使用することをお勧めします。コードで古いバージョンの Internet Explorer をサポートする必要がない限り、var を使用する理由はありません

 

とあるのですが、

「巻き上げって何?」
「varはなぜ使う必要がないの?」
「constは?」

と思ってしまい、いまいち使い分けについて理解できませんでした。

今後の自分のために備忘録として、調べてみたことをメモしたいと思います。

■対象読者

・プログラム初学者の方
・将来の自分

■jsにおけるスコープ

スコープとは?

・変数名や関数名の有効範囲のこと

グローバルスコープ

・関数の外(トップレベル)で宣言した変数
・プログラム全体から参照可能

・関数スコープ

・関数の中で宣言した変数
・その関数の中でのみ参照可能

ブロックスコープ

・ブロックの中で宣言した変数
・そのブロックの中でのみ参照可能

# jsではこれまでブロックスコープは存在しなかったが、
ECMAscript5から「let」が登場し、ブロックスコープを作り出せるようになった。

■巻き上げとは?

JavaScriptは関数内のどこでもvarの宣言を書ける
・関数のどこで宣言しても、先頭で定義したものとしてみなされる
・先頭部分で使いたい変数は全て定義するのが定石

つまり
関数の外で宣言を書けば、コードの先頭
関数の中で宣言を書けば、関数の先頭
で、宣言したと見做されてしまう


■それぞれの性質

var

・変数を宣言する (再代入可能)
・関数スコープである
・巻き上げが起こる

let

・変数を宣言する (再代入可能)
・関数スコープかつブロックスコープでもある
・巻き上げが起こる

const

・定数を宣言する (再代入不可)
・関数スコープかつブロックスコープである
・巻き上げが起こる


■まとめ

・「var」は基本使わない。
・再代入が必要な場合(for文など)は、「let」を使う。
・再代入が不要な場合は、「const」を使う。
・巻き上げはどれを使っても起きるので、変数宣言はスコープの一番上で行う。

 

■参考記事様

・スコープについて

https://qiita.com/Kazuuuuuki/items/3c40bbe6e7bb7ff84e3e

 

・使い分けについて

https://qiita.com/wannabe/items/b2a0d63fc786eab13c48

https://qiita.com/masarufuruya/items/096e51c3e4c36c86ae27

 

プログラミング歴:3か月、初学者によるRails Tutorial完走記

こんばんは!

みなさんはGWいかがお過ごしでしたか? 私はたくさん勉強するぞ!!と意気込んで丸3日ほど勉強時間を確保していたのですが、そこまで捗りませんでした。。。

そんな最終日の夜、GWの余韻を感じながらこの記事を書いております。

 

早速ですが、本題に入っていきたいと思います。

 

(前回までのあらすじは、 ↓ このあたりの過去記事を読んでいただければわかります!)

ここ1ヶ月の学習状況 - Ashiro-days

プログラミング学習記録 〜Rails Tutorial完走しました〜 - Ashiro-days

 

プログラミング初学者がRailsTutorialを完走してみて?

先日、Rails Tutorial(以下、RT)を完走したプログラミング学習歴3ヶ月の筆者が、今の心境を今後の自分への備忘録、そしてこれからRTを利用してRuby on Railsを学ぼうとしている方の役に立てたらと思い、

 

 

完走してよかったこと

・学習コスト(お金)がかからなかった

 

・学習する癖がついた
・手順書に沿ってだが、Webサイトを0から開発することができた。
・想定していないエラーが出た時に検索し、特定するスピードが徐々についた。

 

反省すべき点

・学習コスト(時間、効率)がかかりすぎた

この期間をどう捉えるかは正直人によると思う。学習を初めて一番モチベーションが高い時期をRTに費やすべきかどうかは考えるべきだった。

(作業予定やWBS的なものを作成しなかったので、結果その日その日のやる気やモチベーションに依存した、行き当たりばったりの開発になってしまったことも反省点。)

 

・0-1で全て自分で開発したわけではないため、ポートフォリオにならない。

RTの手順書はとても丁寧。コードのコピペだけで手順自体は止まらずサクサクと作成することが可能なので、RTの成果物では企業へのアピールにはならないと思う。

私はポートフォリオするつもりで作成したわけではないが、最速もしくはなる早でWeb 系エンジニアへのジョブチェンジを目指す人は意識すべき点だと思う。

 

・技術的要素(主にRails,js)についてほとんどわからないまま終えてしまったこと。

当初、手順書をコピペして進めてしまっていたためサクサクと進みすぎて理解が追いつかないことがしばしばあった。途中からそのやり方を見直し、原則全てコードは手で打つようにしたが、理解できないコードもみたまま写してしまい、結果理解できないまま進んでしまう、ということが続いた。

  

・7章を越えたあたりから急激に難易度が上がり、それ以降は手順に沿ってやることしかできなかった。

作業が難しくなる7章以降、以下のようなサイクルを繰り返してばかりだった。

 

1. 技術的に難しい箇所が現れる → 2. 考えるがわからない → 3. 作業が遅れた気がしてくる → 4. 焦って急いで手順を進める → (1. に戻る)

 

今思えば、わからないところ難しいところが現れたのなら、手を止め理解できるように善処すべきだった。RTは基本的にその章までに扱った記述的要素は理解しているものと見做され、手順が進んでいく。そのため、わからないところを放置してしまうとその先の内容も連鎖的に理解できなくなってしまう。

 

・作業に集中しすぎて、アウトプットが極端に少なかった。

道中、行ったアウトプットは、2度のブログ投稿、たまにTwitterくらいだった。これは完全な怠慢だと思っていて、理解が深まらなかった原因と認識している。次回からの学習では毎日の作業予定の中にアウトプットの時間を必ず組込む。

 

まとめ

ここまでつらつらとよかった点悪かった点を挙げてきましたが、言いたいことを三点にまとめてみます!

 

・頭を使って挑むべき

いきなりWebサイト作るぞ!と飛びつくのではなく、やる目的や確保できるリソースを理解し、判断して、やるかどうか決めるべき。

プログラミング初学者が学ぶべき技術要素は、Ruby on Railsだけでなく他にもたくさんあると思うので、精査に時間を掛け、戦略的に挑もう!

 

・焦らず自分のペースでやろう

理解が思ったように進まないと焦ってよくない方向に進みがちです。

そんな時は手を止め深呼吸して今やるべきことを考えましょう。

ネット上の初学者の方の中にはものすごいスピードで勉強し、ジョブチェンジに成功されている方が何人もいらっしゃいますが、そちらと比較するのをやめ、比べるべきは「昨日の自分」と、です。。

 

・アウトプットは学習と並行してやるべき

ポートフォリオとしての価値は低くなってしまうRTの成果物です。

焦って手順を済ましても、あなたがそれを理解していなければなおさら意味がありません。アウトプットに時間を掛け、理解を深めましょう。もしかしたらそのアウトプットがポートフォリオ代わりになるかもしれませんし!

 

 

以上、私のRails Tutorial反省でした。

みなさん、五月病に負けずに今週から頑張りましょう!

 

プログラミング学習記録 〜Rails Tutorial完走しました〜

前回の投稿から2週間が経った本日、

Rail Tutorialの14章が完了、完走いたしました。

f:id:oni_rb:20190504154231p:plain

RailsTuto-Home画面

f:id:oni_rb:20190504154238p:plain

RailsTuto-Users画面

 

13章で記事投稿機能、14章でフォロー/フォロワー機能を追加し、完成させました。

 

Web系技術の初心者として挑戦し、一度は挫折したRail Tutorialでしたが、最後までやり遂げることができてよかった!

しかし、初学者の私にとって完走するために1ヶ月超という多大な労力がかかったことも事実で、皆に勧められる学習方法ではないな、と思いました。

  

いい機会なので、これまでの総括として初学者がRails Tutorialを完走してみるとどうなるのか?って記事を描いてみようかな。

長くなりそうなので、次の記事で!