New-Village

月間ブログ。だいたい1カ月に1回は更新しているようです。

Ruby on Rails チュートリアル on Cloud9 の学習録(第8章)

先週、たまたまbayfmHyadain Stationを聞いてから、ヒャダインにハマっています。この番組は、特定のテーマに従って彼が選曲した曲を流す番組ですが、曲のチョイスと紹介が秀逸です。

ガンダムビルドファイターズの新しいエンディングはヒャダインだったのか(笑)ラジオを聞いていて初めて気づいた。良い歌だと思って聞いたけど全然気づかなかった。


【MV】半パン魂【ヒャダイン】- Hanpan Spirit - Hyadain - YouTube

 第8章 サインイン、サインアウト

まずは、コントローラーの作成とテストの作成。

$ rails generate controller Sessions --no-test-framework

$ rails generate integration_test authentication_pages

 generate integration_testで生成されたテストページを編集。ここで使われている、"subject { page }"の意味が分からない。

8.1.4確認フォームを送信する

&& は論理積。両方の条件がtrueにならない場合は、falseとなる。

8.2.1[このアカウント設定を保存する] 

Ruby標準ライブラリのSecureRandomモジュールにあるurlsafe_base64メソッドを使って、ランダムな16文字のコードを生成する。これを、ウェブアプリのデータベースとユーザーのCookieとして保持して、ログイン時に参照させる仕組み。SSL接続にする事で、傍受の可能性を防ぎつつ、毎回、ログイン後にCookieを再発行することで、成り済ましを防ぐ仕組みを作っている。

この説明で、Subjectの意味が分かった!itが示す主語をsubjectで指定する仕組みなのか。

itsメソッドは、itと似ていますが、itが指すテストのsubject (ここでは@user) そのものではなく、引数として与えられたその属性 (この場合は:remember_token) に対してテストを行うときに使用します。

before_create や priveteについてもここで説明している。

8.2.2正しいsign_inメソッド

Railsは単位換算や時間の計算に強い。

「コラム 8.1cookiesは今から20年後に切れる (20.years.from_now)」

8.2.3現在のユーザー

要素代入 (assignment)についての解説があるが…、全然わからない。

メモ: 今更ながら...defはメソッド。

8.2.4レイアウトリンクを変更する

ややこしいメソッド。"!"が否定で、"current_user.nil?"で「現在のユーザーがnilかどうか確認」しているので、「現在のユーザーがnilではない」場合は真、nilの場合は偽となる。

def signed_in?

    !current_user.nil?

end

条件によって、メニューを変化させるための方法はこの辺に記載されている。なお、リンクをクリックするとペロっと出るメニューを使うには、application.jsにbootstrapを追加する必要がある。

8.2.5ユーザー登録と同時にサインインする

むむむ...致命的ではないから先送りにした、サインアップ後の画面テストだが、以下のように"user"を"User"に変更すると、テストをパスするようになった(追記:これだとDBにname methodがあるかどうか確認している?)。すぐ上で定義している"let(:user)" から取得しているから、小文字で良いような気がするんだけどなぁ…。

×:it { should have_title(user.name) } 

○:it { should have_title(User.name) } 

追記:なおった。"fill_in"している部分と、"let(:user)"で取得しているアドレスが違った事が原因だった。テストDBに"find_by"したときに該当のアドレスが存在しないからエラーになっていたのだと思われる。

追記の追記:帰ってくるエラーは"undefined method `name' for nil:NilClass"であったが、該当のメールアドレスが無いからnilが帰っていたという意味を示していることに、今更気づいた。"undefined method 'name'"という書き方なので、なにか変数を作り忘れているのかと思っていた。

describe "正常系テスト" do

      before do

        fill_in "Name",           with: "Example User"

        fill_in "Email",          with: "example@railstutorial.org"

        fill_in "Password",       with: "foobar"

        fill_in "Confirmation",   with: "foobar"

      end

    

      it "正しく入力して作成ボタンをクリック" do

        expect { click_button submit }.to change(User, :count).by(1)

      end

    

      describe "Sign Up後のユーザー画面表示" do

        before { click_button submit }

        let(:user) { User.find_by(email: 'example@railstutorial.org') }

 

        it { should have_link('Sign out') }

        it { should have_title(user.name) }

        it { should have_selector('div.alert.alert-success', text: 'Welcome') }

      end

    end 

8.3Cucumberの紹介 (オプション)

これは凄いツールだけど、rspecで十分なので今回はパス。 

8.4最後に

ローカルでは全く問題なく動いていたのに、Herokuにアップロードして、Sign upしようとしたら、"We're sorry, but something went wrong."と表示されて先に進めなくなってしまった。ログを調べてみると、remember_tokenでエラーが発生してた。

NoMethodError (undefined method `remember_token=' for #<User:0x00000004070c98>):

app/models/user.rb:23:in `create_remember_token'

app/controllers/users_controller.rb:14:in `create'

 ネットで調べてみると、Heroku NoMethod error, remember_token= で、Herokuアプリを再起動したら動いたという話が書いてあったので、"heroku restart"してみたら、無事に解消された。原因がはっきりしないが、"heroku pg:reset"とかを書けた場合は、アプリのリスタートが必要なようだ。

 追記:herokuで公開できたのは良いが… "https://<app-name>/user/1"とアクセスするとユーザーページが見えてしまう。いいのだろうか?