読者です 読者をやめる 読者になる 読者になる

新米パパの育児留学

子供との幸せな時間を今だけではなく、一生大切にしたいという思いから、育休中にプログラミングを学習しエンジニアを目指します。

転職祝い金50万円のIT・WEB業界特化型転職サービス"Nexstar"を実際に使ってみた感想

ワークスタイル ワークスタイル-転職

f:id:mochikichi321:20170317065210p:plain

Nexstarとは

Nexstarとは、 ITベンチャー企業である株式会社オープンキャリアが提供する、Facebookアプリを用いたIT・WEB業界に特化した転職支援サービスである。

 

株式会社オープンキャリア(open-carrer)(*1)は、2014年に設立されたITベンチャー企業に特化した人材紹介会社であり、東証マザーズ上場の株式会社アイモバイルから誕生した。株式会社アイモバイル(*2)は、インターネット広告システムの構築・配信を主力事業としており、ふるさと納税サイト「ふるなび」等を運営するIT業界において一定の地位と信頼を築いている会社である。

 

(*1)ITベンチャー企業に特化した人材紹介 | open-career

(*2)アイモバイル(i-mobile) 国内最大級のアドネットワーク広告 PC/スマートフォン広告(スマホ広告・アイコン広告・インターステーシャル広告・ウォール広告・レクタングル広告) android iphone広告

 

Nexstarの4つの特徴

Facebookアプリを用いたIT・WEB業界に特化した転職支援サービスであるが、類似サービスとしては「Switch.(*3)」がある。基本的には同様の機能を有していると考えてもらって問題ないが、「Switch.」にはない大きな特徴があるのでそこを含めて以下で説明する。

(*3)Facebookを使った新感覚スカウト型転職サイトSwitch.

1.転職祝い金、50万円!

f:id:mochikichi321:20170318172300p:plain

ここが最大の特徴である。転職祝い金としてAmazonギフト券や現金数万円というサービスは多くあるが、「50万円(*4)」という金額には驚きだ。

転職が決まったら引越しや生活環境の変化等支出が多くなるのでこれは非常に嬉しい。

自分の行きたい企業がNexstarにあれば間違いなくNexstarから申し込んで臨時ボーナスをもらった方がお得だ。

 (*4)理論年収400万円以上の採用でお祝い金50万円、400万円未満の採用の場合はお祝い金30万円

2.簡単1クリック無料登録

f:id:mochikichi321:20170318172311p:plain

そして、登録が簡単だ。登録ボタンを押してFacebookとの連携を認証すればすぐにサービスを開始できる。もちろん、スカウトを受けるためにはプロフィールを充実していった方が好ましいが、まずは登録してみてどのような企業が掲載されていてどのような使い勝手かを「体験」したいのであれば「1クリック」で登録完了する。

 ※Facebookに勝手に投稿されるようなことはないので安心できる。

登録はこちら↓

3.カジュアルメッセージ

f:id:mochikichi321:20170318172320p:plain

興味を持った企業に自分からチャット形式で気軽に質問できる。チャット機能は、メールのように「〇〇株式会社〇〇様 この度は...」といったかしこまった形式ではなく「いつでも気軽に聞きたいことだけ聞ける」ので導入しているサービスは増えてきており人気の問い合わせツールだ。

※「Switch.」にはチャット機能があるが、「マッチング成立後」となっている。「応募する」となるとかなり重い印象を受けた。

 

4.無料の転職サポート

f:id:mochikichi321:20170318172326p:plain

IT・WEB業界経験を持った専門コンサルタントに「転職相談・キャリアの悩み・市場動向」などをチャットで無料相談できる。無料で気軽に何度でも相談できるのでありがたい。

 

実際に使ってみた

上記のような特徴を持っており、すごく興味深いサービスだったので実際に使ってみた。

 

まず1クリック登録をし、どのような企業からの求人があるのかを覗いてみた。

 

以下は一例だが、サイバーエージェントのようなもはやベンチャーではないような大きな企業から、スタートアップのSansanなど個人的に興味を惹かれる企業が並んでいた。(2017年2月現在) 

f:id:mochikichi321:20170318153055p:plain

プロフィール情報を充実させてみると約1週間で7社からスカウトが到来。

f:id:mochikichi321:20170318153112p:plain

その中から、Nexstarの母体でもあるアイモバイルに詳しく聞いてみることに。

チャットでコンタクトを取ると数時間で返答があった。お気軽!

f:id:mochikichi321:20170318153116p:plain

続いてNexstarへ市場動向を問い合わせ。丁寧に返答してくれた。

f:id:mochikichi321:20170322071848p:plain

まとめ

実際に使ってみた感想。

・登録は本当に1クリックでできて簡単。

・シンプルなユーザーインターフェースで使いやすい。

・自分の興味ある企業にチャットで気軽に質問できて使いやすい。

・求人企業の数はまだ多くはないが、面白いベンチャー企業が集まりつつある。今後の拡大に更に期待できる。

 

ワンクリックで簡単に登録できるのでまずは"お試し"で登録してみてはどうだろうか。

縁のある企業が見つかれば晴れてお祝い金50万円GET!!

登録はこちら↓

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習13.1.1

演習13.1.1.1

<問題> RailsコンソールでMicropost.newを実行し、インスタンスを変数micropostに代入してください。その後、user_idに最初のユーザーのidを、contentに “Lorem ipsum” をそれぞれ代入してみてください。この時点では、 micropostオブジェクトのマジックカラム (created_atとupdated_at) には何が入っているでしょうか?

<解答>

>> micropost=Micropost.new
=> #<Micropost id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil>

>> micropost.user_id=1
=> 1
>> micropost.content="Lorem ipsum"
=> "Lorem ipsum"

>> micropost
=> #<Micropost id: nil, content: "Lorem ipsum", user_id: 1, created_at: nil, updated_at: nil>

マジックカラムは"nil"

演習13.1.1.2

<問題> 先ほど作ったオブジェクトを使って、micropost.userを実行してみましょう。どのような結果が返ってくるでしょうか? また、micropost.user.nameを実行した場合の結果はどうなるでしょうか?

<解答>

>> micropost.user
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-02-20 10:41:54", updated_at: "2017-02-20 10:41:54", password_digest: "$2a$10$/kQ3M3tCRo9fdhf4dvYBBezX19bWZk2SJeSkovfkJgB...", remember_digest: nil, admin: true, activation_digest: "$2a$10$gxTIacN4NX5iNR0/H3WayuLkrh7ZGJzsoJG3hSu1WAt...", activated: true, activated_at: "2017-02-20 10:41:54", reset_digest: nil, reset_sent_at: nil>

>> micropost.user.name
=> "Example User"

演習13.1.1.3

<問題> 先ほど作ったmicropostオブジェクトをデータベースに保存してみましょう。この時点でもう一度マジックカラムの内容を調べてみましょう。今度はどのような値が入っているでしょうか?

<解答>

>> micropost.save
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", 2017-02-23 07:52:35 UTC], ["updated_at", 2017-02-23 07:52:35 UTC]]
   (13.0ms)  commit transaction
=> true

マジックカラムには上記の実行日時が入る。

演習13.1.2

演習13.1.2.1

<問題> Railsコンソールを開き、user_idとcontentが空になっているmicropostオブジェクトを作ってみてください。このオブジェクトに対してvalid?を実行すると、失敗することを確認してみましょう。また、生成されたエラーメッセージにはどんな内容が書かれているでしょうか?

<解答> 動作確認のみなので省略。

演習13.1.2.2

<問題> コンソールを開き、今度はuser_idが空でcontentが141文字以上のmicropostオブジェクトを作ってみてください。このオブジェクトに対してvalid?を実行すると、失敗することを確認してみましょう。また、生成されたエラーメッセージにはどんな内容が書かれているでしょうか?

<解答> 動作確認のみなので省略。

演習13.1.3

演習13.1.3.1

<問題> データベースにいる最初のユーザーを変数userに代入してください。そのuserオブジェクトを使ってmicropost = user.microposts.create(content: “Lorem ipsum”)を実行すると、どのような結果が得られるでしょうか?

<解答>

>> user=User.first
  User Load (1.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-02-20 10:41:54", updated_at: "2017-02-20 10:41:54", password_digest: "$2a$10$/kQ3M3tCRo9fdhf4dvYBBezX19bWZk2SJeSkovfkJgB...", remember_digest: nil, admin: true, activation_digest: "$2a$10$gxTIacN4NX5iNR0/H3WayuLkrh7ZGJzsoJG3hSu1WAt...", activated: true, activated_at: "2017-02-20 10:41:54", reset_digest: nil, reset_sent_at: nil>

>> micropost = user.microposts.create(content: "Lorem ipsum")
   (0.1ms)  begin transaction
  SQL (2.1ms)  INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["content", "Lorem ipsum"], ["user_id", 1], ["created_at", 2017-02-23 08:21:53 UTC], ["updated_at", 2017-02-23 08:21:53 UTC]]
   (13.0ms)  commit transaction
=> #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2017-02-23 08:21:53", updated_at: "2017-02-23 08:21:53">

演習13.1.3.2

<問題> 先ほどの演習課題で、データベース上に新しいマイクロポストが追加されたはずです。 user.microposts.find(micropost.id)を実行して、本当に追加されたのかを確かめてみましょう。また、先ほど実行したmicropost.idの部分をmicropostに変更すると、結果はどうなるでしょうか?

<解答>

>> user.microposts.find(micropost.id)
  Micropost Load (0.3ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? AND "microposts"."id" = ? LIMIT ?  [["user_id", 1], ["id", 2], ["LIMIT", 1]]
=> #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2017-02-23 08:21:53", updated_at: "2017-02-23 08:21:53">

>> user.microposts.find(micropost)
DEPRECATION WARNING: You are passing an instance of ActiveRecord::Base to `find`. Please pass the id of the object by calling `.id`. (called from irb_binding at (irb):4)
  Micropost Load (0.2ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? AND "microposts"."id" = ? LIMIT ?  [["user_id", 1], ["id", 2], ["LIMIT", 1]]
=> #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2017-02-23 08:21:53", updated_at: "2017-02-23 08:21:53">

micropost.idの部分をmicropostに変更するとidを指定するよう要求される

演習13.1.3.3

<問題> user == micropost.userを実行した結果はどうなるでしょうか? また、user.microposts.first == micropost を実行した結果はどうなるでしょうか? それぞれ確認してみてください。

>> user == micropost.user
=> true

>> user.microposts.first == micropost
  Micropost Load (0.4ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."id" ASC LIMIT ?  [["user_id", 1], ["LIMIT", 1]]
=> false

micropost id:2なので、user.microposts.first != micropost

演習13.1.4

演習13.1.4.1

<問題> Micropost.first.created_atの実行結果と、Micropost.last.created_atの実行結果を比べてみましょう。

<解答>

>> Micropost.first.created_at
  Micropost Load (1.7ms)  SELECT  "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ?  [["LIMIT", 1]]
=> Thu, 23 Feb 2017 08:21:53 UTC +00:00

>> Micropost.last.created_at
  Micropost Load (0.4ms)  SELECT  "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ?  [["LIMIT", 1]]
=> Thu, 23 Feb 2017 07:52:35 UTC +00:00

演習13.1.4.2

<問題> Micropost.firstを実行したときに発行されるSQL文はどうなっているでしょうか? 同様にして、Micropost.lastの場合はどうなっているでしょうか? ヒント: それぞれをコンソール上で実行したときに表示される文字列が、SQL文になります。

<解答>

>> Micropost.first
  Micropost Load (0.2ms)  SELECT  "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" DESC LIMIT ?  [["LIMIT", 1]]
=> #<Micropost id: 2, content: "Lorem ipsum", user_id: 1, created_at: "2017-02-23 08:21:53", updated_at: "2017-02-23 08:21:53">

>> Micropost.last
  Micropost Load (0.2ms)  SELECT  "microposts".* FROM "microposts" ORDER BY "microposts"."created_at" ASC LIMIT ?  [["LIMIT", 1]]
=> #<Micropost id: 1, content: "Lorem ipsum", user_id: 1, created_at: "2017-02-23 07:52:35", updated_at: "2017-02-23 07:52:35">

Micropost.firstはDESC Micropost.lastはASC

演習13.1.4.3

<問題> データベース上の最初のユーザーを変数userに代入してください。そのuserオブジェクトが最初に投稿したマイクロポストのidはいくつでしょうか? 次に、destroyメソッドを使ってそのuserオブジェクトを削除してみてください。削除すると、そのuserに紐付いていたマイクロポストも削除されていることをMicropost.findで確認してみましょう。

<解答> 動作確認のみなので省略。

演習13.2.1

演習13.2.1.1

<問題> 7.3.3で軽く説明したように、今回ヘルパーメソッドとして使ったtime_ago_in_wordsメソッドは、Railsコンソールのhelperオブジェクトから呼び出すことができます。このhelperオブジェクトのtime_ago_in_wordsメソッドを使って、3.weeks.agoや6.months.agoを実行してみましょう。

<解答> 動作確認のみなので省略。

演習13.2.1.2

<問題> helper.time_ago_in_words(1.year.ago)と実行すると、どういった結果が返ってくるでしょうか?

<解答>

>> helper.time_ago_in_words(1.year.ago)
=> "about 1 year"

演習13.2.1.3

<問題> micropostsオブジェクトのクラスは何でしょうか? ヒント: リスト 13.23内のコードににあるように、まずはpaginateメソッド (引数はpage: nil) でオブジェクトを取得し、その後classメソッドを呼び出してみましょう。

<解答>

>> user=User.first
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-02-23 11:51:52", updated_at: "2017-02-23 11:51:52", password_digest: "$2a$10$ZN5cjKOsES4dYHA/QRijX.4wJG.cFLhUkciP2cYhROy...", remember_digest: nil, admin: true, activation_digest: "$2a$10$e7ScgLHWk1IcYzvOXRt08.KOV.YZ/z.h9QI1imwG3Ez...", activated: true, activated_at: "2017-02-23 11:51:52", reset_digest: nil, reset_sent_at: nil>

>> microposts = user.microposts.paginate(page: nil)
  Micropost Load (0.3ms)  SELECT  "microposts".* FROM "microposts" WHERE "microposts"."user_id" = ? ORDER BY "microposts"."created_at" DESC LIMIT ? OFFSET ?  [["user_id", 1], ["LIMIT", 30], ["OFFSET", 0]]
=> #<ActiveRecord::AssociationRelation []>

>> microposts.class
=> Micropost::ActiveRecord_AssociationRelation

演習13.2.2

演習13.2.2.1

<問題> (1..10).to_a.take(6)というコードの実行結果を推測できますか? 推測した値が合っているかどうか、実際にコンソールを使って確認してみましょう。

<解答>

>> (1..10).to_a.take(6)
=> [1, 2, 3, 4, 5, 6]

演習13.2.2.1

<問題> 先ほどの演習にあったto_aメソッドの部分は本当に必要でしょうか? 確かめてみてください。

<解答> 不要。

演習13.2.2.1

<問題> Fakerはlorem ipsum以外にも、非常に多種多様の事例に対応しています。Fakerのドキュメント (英語) を眺めながら画面に出力する方法を学び、実際に大学名や電話番号、Hipster IpsumやChuck Norris facts (参考: チャック・ノリスの真実) を画面に出力してみましょう。(訳注: もちろん日本語にも対応していて、例えば沖縄らしい用語を出力するfaker-okinawaもあります。ぜひ遊んでみてください。)

<解答> 動作確認のみなので省略。

演習13.2.3

演習13.2.3.1

<問題> リスト 13.28にある2つの’h1’行をコメントアウトしてみて、テストが green から redに変わることを確認してみましょう。

<解答> 動作確認のみなので省略。 ※実際にコメントアウトするのは"リスト 13.24"の'h1'の中の2行。

演習13.2.3.2

<問題> リスト 13.28にあるテストを変更して、will_paginateが少なくとも1度は表示されていることをテストしてみましょう。ヒント: 表 5.2を参考にしてください。

<解答>

[users_profile_test.rb]

require 'test_helper'

class UsersProfileTest < ActionDispatch::IntegrationTest
  include ApplicationHelper

  def setup
    @user = users(:michael)
  end

  test "profile display" do
    get user_path(@user)
    assert_template 'users/show'
    assert_select 'title', full_title(@user.name)
    assert_select 'h1', text: @user.name
    assert_select 'h1>img.gravatar'
    assert_match @user.microposts.count.to_s, response.body
    assert_select 'div.pagination', count:1   <---注目
    @user.microposts.paginate(page: 1).each do |micropost|
      assert_match micropost.content, response.body
    end
  end
end

演習13.3.1

演習13.3.1.1

<問題> なぜUsersコントローラ内にあるlogged_in_userフィルターを残したままにするとマズイのでしょうか? 考えてみてください。

<解答> コードが重複するため。

演習13.3.2

演習13.3.2.1

<問題> Homeページをリファクタリングして、if-else文の分岐のそれぞれに対してパーシャルを作ってみましょう。

<解答>

[home.html.erb]

<% if logged_in? %>
  <%= render 'static_pages/user_logged_in' %>
<% else %>
  <%= render 'static_pages/user_not_logged_in' %>
<% end %>

[_user_logged_in.html.erb]

  <div class="row">
    <aside class="col-md-4">
      <section class="user_info">
        <%= render 'shared/user_info' %>
      </section>
      <section class="micropost_form">
        <%= render 'shared/micropost_form' %>
      </section>
    </aside>
  </div>

[_user_not_logged_in.html.erb]

  <div class="center jumbotron">
    <h1>Welcome to the Sample App</h1>

    <h2>
      This is the home page for the
      <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
      sample application.
    </h2>

    <%= link_to "Sign up now!", signup_path, class: "btn btn-lg btn-primary" %>
  </div>

  <%= link_to image_tag("rails.png", alt: "Rails logo"),
              'http://rubyonrails.org/' %>

演習13.3.3

演習13.3.3.1

<問題> 新しく実装したマイクロポストの投稿フォームを使って、実際にマイクロポストを投稿してみましょう。Railsサーバーのログ内にあるINSERT文では、どういった内容をデータベースに送っているでしょうか? 確認してみてください。

<解答>

 INSERT INTO "microposts" ("content", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["content", "aaa"], ["user_id", 1], ["created_at", 2017-02-24 01:41:51 UTC], ["updated_at", 2017-02-24 01:41:51 UTC]]

演習13.3.3.2

<問題> コンソールを開き、user変数にデータベース上の最初のユーザーを代入してみましょう。その後、Micropost.where(“user_id = ?”, user.id)とuser.microposts、そしてuser.feedをそれぞれ実行してみて、実行結果がすべて同じであることを確認してみてください。ヒント: ==で比較すると結果が同じかどうか簡単に判別できます。

<解答> 動作確認のみなので省略。

演習13.3.4

演習13.3.4.1

<問題> マイクロポストを作成し、その後、作成したマイクロポストを削除してみましょう。次に、Railsサーバーのログを見てみて、DELETE文の内容を確認してみてください。

<解答> 動作確認のみなので省略。

演習13.3.4.2

<問題> redirect_to request.referrer || root_urlの行をredirect_back(fallback_location: root_url)と置き換えてもうまく動くことを、ブラウザを使って確認してみましょう (このメソッドはRails 5から新たに導入されました)。

<解答> 動作確認のみなので省略。

演習13.3.5

演習13.3.5.1

<問題> リスト 13.55で示した4つのコメント (「無効な送信」など) のそれぞれに対して、テストが正しく動いているか確認してみましょう。具体的には、対応するアプリケーション側のコードをコメントアウトし、テストが redになることを確認し、元に戻すと greenになることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習13.3.5.2

<問題> サイドバーにあるマイクロポストの合計投稿数をテストしてみましょう。このとき、単数形 (micropost) と複数形 (microposts) が正しく表示されているかどうかもテストしてください。ヒント: リスト 13.57を参考にしてみてください。

<解答>

[microposts_interface_test.rb]

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

(中略)

  test "micropost sidebar count" do
    log_in_as(@user)
    get root_path
    assert_match "#{@user.microposts.count} microposts", response.body   <---注目
    # まだマイクロポストを投稿していないユーザー
    other_user = users(:malory)
    log_in_as(other_user)
    get root_path
    assert_match "0 microposts", response.body
    other_user.microposts.create!(content: "A micropost")
    get root_path
    assert_match "1 micropost", response.body   <---注目
  end
end

演習13.4.1

演習13.4.1.1

<問題> 画像付きのマイクロポストを投稿してみましょう。もしかして、大きすぎる画像が表示されてしまいましたか? (心配しないでください、次の13.4.3でこの問題を直します)。

<解答> 動作確認のみなので省略。

演習13.4.1.2

<問題> リスト 13.63に示すテンプレートを参考に、13.4で実装した画像アップローダーをテストしてください。テストの準備として、まずはサンプル画像をfixtureディレクトリに追加してください (コマンド例: cp app/assets/images/rails.png test/fixtures/)。リスト 13.63で追加したテストでは、Homeページにあるファイルアップロードと、投稿に成功した時に画像が表示されているかどうかをチェックしています。なお、テスト内にあるfixture_file_uploadというメソッドは、fixtureで定義されたファイルをアップロードする特別なメソッドです16。ヒント: picture属性が有効かどうかを確かめるときは、11.3.3で紹介したassignsメソッドを使ってください。このメソッドを使うと、投稿に成功した後にcreateアクション内のマイクロポストにアクセスするようになります。

<解答>

[microposts_interface_test.rb]

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'div.pagination'
    assert_select 'input[type="file"]'   <---注目
    # 無効な送信
    post microposts_path, micropost: { content: "" }
    assert_select 'div#error_explanation'
    # 有効な送信
    content = "This micropost really ties the room together"
    picture = fixture_file_upload('test/fixtures/rails.png', 'image/png')
    assert_difference 'Micropost.count', 1 do
      post microposts_path, micropost: { content: content, picture: picture }   <---注目
    end
    assert assigns(:micropost).picture?   <---注目
    follow_redirect!
    assert_match content, response.body
    # 投稿を削除する
    assert_select 'a', text: 'delete'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end
    # 違うユーザーのプロフィールにアクセス (削除リンクがないことを確認)
    get user_path(users(:archer))
    assert_select 'a', text: 'delete', count: 0
  end

(中略)

end

演習13.4.2

演習13.4.2.1

<問題> 5MB以上の画像ファイルを送信しようとした場合、どうなりますか?

<解答> エラーが出る。

演習13.4.2.2

<問題> 無効な拡張子のファイルを送信しようとした場合、どうなりますか?

<解答> エラーが出る。

演習13.4.3

演習13.4.3.1

<問題> 解像度の高い画像をアップロードし、リサイズされているかどうか確認してみましょう。画像が長方形だった場合、リサイズはうまく行われているでしょうか?

<解答> 確認は省略。長方形の場合は、長い辺が400pxとなるようにリサイズされる。

演習13.4.3.2

<問題> 既にリスト 13.63のテストを追加していた場合、この時点でテストスイートを走らせるとエラーメッセージが表示されるようになるはずです。このエラーを取り除いてみましょう。ヒント: リスト 13.68にある設定ファイルを修正し、テスト時はCarrierWaveに画像のリサイズをさせないようにしてみましょう。

<解答> リスト 13.68参照。

演習13.4.4

演習13.4.4.1

<問題> 本番環境で解像度の高い画像をアップロードし、適切にリサイズされているか確認してみましょう。長方形の画像であっても、適切にリサイズされていますか?

<解答> 動作確認のみなので省略。

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習12.1.1

演習12.1.1.1

<問題> この時点で、テストスイートが greenになっていることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習12.1.1.2

<問題> 表 12.1の名前付きルートでは、pathではなくurlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: アカウント有効化で行った演習 (11.1.1.1) と同じ理由です。

<解答> 演習 (11.1.1.1) と同じ。

演習12.1.2

演習12.1.2.1

<問題> リスト 12.4のform_forメソッドでは、なぜ@password_resetではなく:password_resetを使っているのでしょうか? 考えてみてください。

<解答> シンボルを使うとよりシンプルなformタグが生成され、オブジェクトを渡すとそのオブジェクトに寄って良しなに出し分けてくれる。newやeditのviewを準備する時に、同じ_form部分テンプレートを利用した時、同じ書き方で出し分けてくれる。 (参考:http://ja.stackoverflow.com/questions/18099/rails%E3%81%AEform-for%E3%81%AB%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AB%E3%82%92%E4%B8%8E%E3%81%88%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AF%E3%81%A9%E3%81%AE%E3%82%88%E3%81%86%E3%81%AA%E3%81%A8%E3%81%8D%E3%81%8B

演習12.1.3

演習12.1.3.1

<問題> 試しに有効なメールアドレスをフォームから送信してみましょう (図 12.6)。どんなエラーメッセージが表示されたでしょうか?

<解答> f:id:mochikichi321:20170309084455p:plain

演習12.1.3.2

<問題> コンソールに移り、先ほどの演習課題で送信した結果、(エラーと表示されてはいるものの) 該当するuserオブジェクトにはreset_digestとreset_sent_atがあることを確認してみましょう。また、それぞれの値はどのようになっていますか?

<解答> reset_digestとreset_sent_at共に値は"nil"となっている。

演習12.2.1

演習12.2.1.1

<問題> ブラウザから、送信メールのプレビューをしてみましょう。「Date」の欄にはどんな情報が表示されているでしょうか?

<解答> Dateはブラウザでメールを表示した時点の日時。

演習12.2.1.2

<問題> パスワード再設定フォームから有効なメールアドレスを送信してみましょう。また、Railsサーバーのログを見て、生成された送信メールの内容を確認してみてください。

<解答> 動作確認のみなので省略。

演習12.2.1.3

<問題> コンソールに移り、先ほどの演習課題でパスワード再設定をしたUserオブジェクトを探してください。オブジェクトを見つけたら、そのオブジェクトが持つreset_digestとreset_sent_atの値を確認してみましょう。

<解答>

reset_digest: "$2a$10$ymOyGT8NRw5KEL/EvODcMupxE8/YKvSklgHMT0ZT3a1...", 
reset_sent_at: "2017-02-22 13:33:50"

演習12.2.2

演習12.2.2.1

<問題> メイラーのテストだけを実行してみてください。このテストは greenになっているでしょうか?

<解答> GREEN

演習12.2.2.2

<問題> リスト 12.12にある2つ目のCGI.escapeを削除すると、テストが redになることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習12.3.1

演習12.3.1.1

<問題> 12.2.1.1で示した手順に従って、Railsサーバーのログから送信メールを探し出し、そこに記されているリンクを見つけてください。そのリンクをブラウザから表示してみて、図 12.11のように表示されるか確かめてみましょう。

<解答> 動作確認のみなので省略。

演習12.3.1.2

<問題> 先ほど表示したページから、実際に新しいパスワードを送信してみましょう。どのような結果になるでしょうか?

<解答> f:id:mochikichi321:20170309084532p:plain

演習12.3.2

演習12.3.2.1

<問題> 12.2.1.1で得られたリンク (Railsサーバーのログから取得) をブラウザで表示し、passwordとconfirmationの文字列をわざと間違えて送信してみましょう。どんなエラーメッセージが表示されるでしょうか?

<解答> The form contains 1 error. Password confirmation doesn’t match Password

演習12.3.2.2

<問題> コンソールに移り、パスワード再設定を送信したユーザーオブジェクトを見つけてください。見つかったら、そのオブジェクトのpassword_digestの値を取得してみましょう。次に、パスワード再設定フォームから有効なパスワードを入力し、送信してみましょう (図 12.13)。パスワードの再設定は成功したら、再度password_digestの値を取得し、先ほど取得した値と異なっていることを確認してみましょう。ヒント: 新しい値はuser.reloadを通して取得する必要があります。

<解答> 動作確認のみなので省略。

演習12.3.3

演習12.3.3.1

<問題> リスト 12.6にあるcreate_reset_digestメソッドはupdate_attributeを2回呼び出していますが、これは各行で1回ずつデータベースへ問い合わせしていることになります。リスト 12.20に記したテンプレートを使って、update_attributeの呼び出しを1回のupdate_columns呼び出しにまとめてみましょう (これでデータベースへの問い合わせが1回で済むようになります)。また、変更後にテストを実行し、 greenになることも確認してください。ちなみにリスト 12.20にあるコードには、前章の演習 (リスト 11.39) の解答も含まれています。

<解答>

[user.rb]

(前略)
  # パスワード再設定の属性を設定する
  def create_reset_digest
    self.reset_token = User.new_token
    update_columns(reset_digest:  User.digest(reset_token), reset_sent_at: Time.zone.now)
  end

演習12.3.3.2

<問題> リスト 12.16のテンプレートを埋めて、期限切れのパスワード再設定で発生する分岐 (リスト 12.21) を統合テストで網羅してみましょう (12.21 のコードにあるresponse.bodyは、そのページのHTML本文をすべて返すメソッドです)。 期限切れをテストする方法はいくつかありますが、リスト 12.21でオススメした手法を使えば、レスポンスの本文に「expired」という語があるかどうかでチェックできます (なお、大文字と小文字は区別されません)。

<解答>

[password_resets_test.rb]

(前略)
  test "expired token" do
    get new_password_reset_path
    post password_resets_path,
         params: { password_reset: { email: @user.email } }

    @user = assigns(:user)
    @user.update_attribute(:reset_sent_at, 3.hours.ago)
    patch password_reset_path(@user.reset_token),
          params: { email: @user.email,
                    user: { password:              "foobar",
                            password_confirmation: "foobar" } }
    assert_response :redirect
    follow_redirect!
    assert_match "expired", response.body   <---注目
  end

演習12.3.3.3

<問題> 2時間経ったらパスワードを再設定できなくする方針は、セキュリティ的に好ましいやり方でしょう。しかし、もっと良くする方法はまだあります。例えば、公共の (または共有された) コンピューターでパスワード再設定が行われた場合を考えてみてください。仮にログアウトして離席したとしても、2時間以内であれば、そのコンピューターの履歴からパスワード再設定フォームを表示させ、パスワードを更新してしまうことができてしまいます (しかもそのままログイン機構まで突破されてしまいます!)。この問題を解決するために、リスト 12.22のコードを追加し、パスワードの再設定に成功したらダイジェストをnilになるように変更してみましょう3。

<解答> 動作確認のみなので省略。

演習12.3.3.4

<問題> リスト 12.18に1行追加し、1つ前の演習課題に対するテストを書いてみましょう。ヒント: リスト 9.25のassert_nilメソッドとリスト 11.33のuser.reloadメソッドを組み合わせて、reset_digest属性を直接テストしてみましょう。

<解答>

[password_resets_test.rb]

require 'test_helper'

class PasswordResetsTest < ActionDispatch::IntegrationTest

(中略)

  test "password resets" do

(中略)

    assert_redirected_to user
    assert_nil user.reload['reset_digest']   <---注目
  end

演習12.4

演習12.4.1

<問題> production環境でユーザー登録を試してみましょう。ユーザー登録時に入力したメールアドレスにメールは届きましたか?

<解答> 動作確認のみなので省略。

演習12.4.2

<問題> メールを受信できたら、実際にメールをクリックしてアカウントを有効化してみましょう。また、Heroku上のログを調べてみて、有効化に関するログがどうなっているのか調べてみてください。ヒント: ターミナルからheroku logsコマンドを実行してみましょう。

<解答> 動作確認のみなので省略。

演習12.4.3

<問題> アカウントを有効化できたら、今度はパスワードの再設定を試してみましょう。正しくパスワードの再設定ができたでしょうか?

<解答> 動作確認のみなので省略。

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習11.1.1

演習11.1.1.1

<問題> 現時点でテストスイートを実行すると greenになることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.1.1.2

<問題> 表 11.2の名前付きルートでは、pathではなくurlを使うように記してあります。なぜでしょうか? 考えてみましょう。ヒント: 私達はこれからメールで名前付きルートを使います。

<解答> メールのURLからアクセスするため。

演習11.1.2

演習11.1.2.1

<問題> 本項での変更を加えた後、テストスイートが green のままになっていることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.1.2.2

<問題> コンソールからUserクラスのインスタンスを生成し、そのオブジェクトからcreate_activation_digestメソッドを呼び出そうとすると (Privateメソッドなので) NoMethodErrorが発生することを確認してみましょう。また、そのUserオブジェクトからダイジェストの値も確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.1.2.3

<問題> リスト 6.34で、メールアドレスの小文字化にはemail.downcase!という (代入せずに済む) メソッドがあることを知りました。このメソッドを使って、リスト 11.3のdowncase_emailメソッドを改良してみてください。また、うまく変更できれば、テストスイートは成功したままになっていることも確認してみてください。

<解答>

[user.rb]

class User < ApplicationRecord
  attr_accessor :remember_token, :activation_token
  before_save { email.downcase! }  <---注目
(中略)

  private

    # メールアドレスをすべて小文字にする
    # def downcase_email                 <---不要
    #   self.email = email.downcase
    # end
(中略)
end

テストはGREEN。

演習11.2.1

演習11.2.1.1

<問題> コンソールを開き、CGIモジュールのescapeメソッド (リスト 11.15) でメールアドレスの文字列をエスケープできることを確認してみましょう。このメソッドで"Don’t panic!“をエスケープすると、どんな結果になりますか?

<解答>

>> CGI.escape('Don’t panic!')
=> "Don%E2%80%99t+panic%21"

演習11.2.2

演習11.2.2.1

<問題> Railsプレビュー機能を使って、ブラウザから先ほどのメールを表示してみてください。「Date」の欄にはどんな内容が表示されているでしょうか?

<解答> Dateはブラウザでメールを表示した時点の日時。

演習11.2.3

演習11.2.3.1

<問題> この時点で、テストスイートが greenになっていることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.2.3.2

<問題> リスト 11.20で使ったCGI.escapeの部分を削除すると、テストが redに変わることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.2.4

演習11.2.4.1

<問題> 新しいユーザーを登録したとき、リダイレクト先が適切なURLに変わったことを確認してみましょう。その後、Railsサーバーのログから送信メールの内容を確認してみてください。有効化トークンの値はどうなっていますか?

<解答>

https://rails-tutorial-mhartl.c9users.io/account_activations/wGEP2viu2WQbS9n36A41Lg/edit?email=2%40gmail.com

演習11.2.4.2

<問題> コンソールを開き、データベース上にユーザーが作成されたことを確認してみましょう。また、このユーザーはデータベース上にはいますが、有効化のステータスがfalseのままになっていることを確認してください。

<解答> 動作確認のみなので省略。

演習11.3.1

演習11.3.1.1

<問題> コンソール内で新しいユーザーを作成してみてください。新しいユーザーの記憶トークンと有効化トークンはどのような値になっているでしょうか? また、各トークンに対応するダイジェストの値はどうなっているでしょうか?

<解答> 動作確認のみなので省略。

演習11.3.1.2

<問題> リスト 11.26で抽象化したauthenticated?メソッドを使って、先ほどの各トークン/ダイジェストの組み合わせで認証が成功することを確認してみましょう。

<解答> 動作確認のみなので省略。

演習11.3.2

演習11.3.2.1

<問題> コンソールから、11.2.4で生成したメールに含まれているURLを調べてみてください。URL内のどこに有効化トークンが含まれているでしょうか?

<解答>

https://rails-tutorial-mhartl.c9users.io/account_activations/wGEP2viu2WQbS9n36A41Lg/edit?email=2%40gmail.com

“wGEP2viu2WQbS9n36A41Lg"が有効化トークン。

演習11.3.2.2

<問題> 先ほど見つけたURLをブラウザに貼り付けて、そのユーザーの認証に成功し、有効化できることを確認してみましょう。また、有効化ステータスがtrueになっていることをコンソールから確認してみてください。

<解答> 動作確認のみなので省略。

演習11.3.3

演習11.3.3.1

<問題> リスト 11.35にあるactivateメソッドはupdate_attributeを2回呼び出していますが、これは各行で1回ずつデータベースへ問い合わせしていることになります。リスト 11.39に記したテンプレートを使って、update_attributeの呼び出しを1回のupdate_columns呼び出しにまとめてみましょう (これでデータベースへの問い合わせが1回で済むようになります)。また、変更後にテストを実行し、 greenになることも確認してください。

<解答>

[user.rb]

class User < ApplicationRecord

(中略)

  # アカウントを有効にする
  def activate
    update_columns(activated: true, activated_at: Time.zone.now)
  end

(後略)

演習11.3.3.2

<問題> 現在は、/usersのユーザーindexページを開くとすべてのユーザーが表示され、/users/:idのようにIDを指定すると個別のユーザーを表示できます。しかし考えてみれば、有効でないユーザーは表示する意味がありません。そこで、リスト 11.40のテンプレートを使って、この動作を変更してみましょう8。なお、ここで使っているActive Recordのwhereメソッドについては、13.3.3でもう少し詳しく説明します。

<解答>

[users_controller.rb]

class UsersController < ApplicationController
  before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
  before_action :correct_user,   only: [:edit, :update]
  before_action :admin_user,     only: :destroy
  
  def index
    @users = User.where(activated: true).paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
    redirect_to root_url and return unless @user.activated?
  end

(後略)

演習11.4

演習11.4.1

<問題> 実際に本番環境でユーザー登録をしてみましょう。ユーザー登録時に入力したメールアドレスにメールは届きましたか?

<解答> 動作確認のみなので省略。

演習11.4.2

<問題> メールを受信できたら、実際にメールをクリックしてアカウントを有効化してみましょう。また、Heroku上のログを調べてみて、有効化に関するログがどうなっているのか調べてみてください。ヒント: ターミナルからheroku logsコマンドを実行してみましょう。

<解答> 動作確認のみなので省略。

<a href="https://&lt;your heroku app&gt;.herokuapp.com/account_activations/uiXkg8zRNKlluX3pX7-vwg/edit?email=mochikichi%40live.jp">Activate</a>

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習10.1.1

演習10.1.1.1

<問題> 先ほど触れたように、target=“_blank"で新しいページを開くときには、セキュリティ上の小さな問題があります。それは、リンク先のサイトがHTMLドキュメントのwindowオブジェクトを扱えてしまう、という点です。具体的には、フィッシング (Phising) サイトのような、悪意のあるコンテンツを導入させられてしまう可能性があります。Gravatarのような著名なサイトではこのような事態は起こらないと思いますが、念のため、このセキュリティ上のリスクも排除しておきましょう。対処方法は、リンク用のaタグのrel (relationship) 属性に、"noopener"と設定するだけです。早速、リスト 10.2で使ったGravatarの編集ページへのリンクにこの設定をしてみましょう。

<解答> 指示通り実行するのみなので省略。

演習10.1.1.2

<問題> リスト 10.5のパーシャルを使って、new.html.erbビュー (リスト 10.6) とedit.html.erbビュー (リスト 10.7) をリファクタリングしてみましょう (コードの重複を取り除いてみましょう)。ヒント: 3.4.3で使ったprovideメソッドを使うと、重複を取り除けます3。(関連するリスト 7.27の演習課題を既に解いている場合、この演習課題をうまく解けない可能性があります。うまく解けない場合は、既存のコードのどこに差異があるのか考えながらこの課題に取り組んでみましょう。例えば筆者であれば、リスト 10.5のテクニックをリスト 10.6に適用してみたり、リスト 10.7のテクニックをリスト 10.5に適用してみたりするでしょう。)

<解答> リスト10.5,10.6,10.7参照。

リスト 7.27の演習課題を既に解いている場合は以下。

[new.html.erb]の以下の",url: signup_path"が[edit.html.erb]と異なるため、provideで指定。

<%= form_for(@user,url: signup_path) do |f| %>

[_form.html.erb]

<%= form_for(@user, url: yield(:url)) do |f| %>   <---注目
  <%= render 'shared/error_messages', object: @user %>

  <%= f.label :name %>
  <%= f.text_field :name, class: 'form-control' %>

  <%= f.label :email %>
  <%= f.email_field :email, class: 'form-control' %>

  <%= f.label :password %>
  <%= f.password_field :password, class: 'form-control' %>

  <%= f.label :password_confirmation %>
  <%= f.password_field :password_confirmation, class: 'form-control' %>

  <%= f.submit yield(:button_text), class: "btn btn-primary" %>
<% end %>

[new.html.erb]

<% provide(:title, 'Sign up') %>
<% provide(:url, signup_path) %>   <---注目
<% provide(:button_text, 'Create my account') %>
<h1>Sign up</h1>
<div class="row">
  <div class="col-md-6 col-md-offset-3">
      <%= render 'form' %>
  </div>
</div>

[edit.html.erb]
<% provide(:title, "Edit user") %>
<% provide(:url, user_path) %>   <---注目
<% provide(:button_text, 'Save changes') %>
<h1>Update your profile</h1>
<div class="row">
  <div class="col-md-6 col-md-offset-3">
      <%= render 'form' %>
    <div class="gravatar_edit">
      <%= gravatar_for @user %>
      <a href="http://gravatar.com/emails" target="_blank" rel="noopener">change</a>
    </div>
  </div>
</div>

演習10.1.2

演習10.1.2.1

<問題> 編集フォームから有効でないユーザー名やメールアドレス、パスワードを使って送信した場合、編集に失敗することを確認してみましょう。

<解答> 動作確認のみなので省略。

演習10.1.3

演習10.1.3.1

<問題> リスト 10.9のテストに1行追加し、正しい数のエラーメッセージが表示されているかテストしてみてましょう。ヒント: 表 5.2で紹介したassert_selectを使ってalertクラスのdivタグを探しだし、「The form contains 4 errors.」というテキストを精査してみましょう。

<解答>

[users_edit_test.rb]

require 'test_helper'

class UsersEditTest < ActionDispatch::IntegrationTest

   (中略)

  test "unsuccessful edit" do
 
   (中略)

    assert_template 'users/edit'
    assert_select "div.alert", "The form contains 4 errors."   <---注目
  end
end

演習10.1.4

演習10.1.4.1

<問題> 実際に編集が成功するかどうか、有効な情報を送信して確かめてみましょう。

<解答> 動作確認のみなので省略。

演習10.1.4.2

<問題> もしGravatarと紐付いていない適当なメールアドレス (foobar@example.comなど) に変更した場合、プロフィール画像はどのように表示されるでしょうか? 実際に編集フォームからメールアドレスを変更して、確認してみてましょう。

<解答> 動作確認のみなので省略。

演習10.2.1

演習10.2.1.1

<問題> デフォルトのbeforeフィルターは、すべてのアクションに対して制限を加えます。今回のケースだと、ログインページやユーザー登録ページにも制限の範囲が及んでしまうはずです (結果としてテストも失敗するはずです)。リスト 10.15のonly:オプションをコメントアウトしてみて、テストスイートがそのエラーを検知できるかどうか (テストが失敗するかどうか) 確かめてみましょう。

<解答> 動作確認のみなので省略。

演習10.2.2

演習10.2.2.1

<問題> 何故editアクションとupdateアクションを両方とも保護する必要があるのでしょうか? 考えてみてください。

<解答> それぞれのパスが異なるため。 edit_user GET /users/:id/edit(.:format) users#edit user PATCH /users/:id(.:format) users#update

演習10.2.2.2

<問題> 上記のアクションのうち、どちらがブラウザで簡単にテストできるアクションでしょうか?

<解答> editアクション。 GETメソッドのeditの方がURLを打ち込んでアクセスするのみなので簡単。

演習10.2.3

演習10.2.3.1

<問題> フレンドリーフォワーディングで、最初に渡されたURLにのみ確実に転送されていることを確認するテストを作成してみましょう。続けて、ログインを行った後、転送先のURLはデフォルト (プロフィール画面) に戻る必要もありますので、これもテストで確認してみてください。ヒント: リスト10.29のsession[:forwarding_url]が正しい値かどうかを確認するテストを追加してみましょう。

<解答>

[users_edit_test.rb]

require 'test_helper'

class UsersEditTest < ActionDispatch::IntegrationTest

(中略)

  test "successful edit with friendly forwarding" do
    get edit_user_path(@user)
    assert session[:forwarding_url]   <---注目
    log_in_as(@user)
    assert_redirected_to edit_user_url(@user) || default   <---注目
    name  = "Foo Bar"
    email = "foo@bar.com"
    patch user_path(@user), params: { user: { name:  name,
                                              email: email,
                                              password:              "",
                                              password_confirmation: "" } }
    assert_not flash.empty?
    assert_redirected_to @user
    @user.reload
    assert_equal name,  @user.name
    assert_equal email, @user.email
  end
end

演習10.2.3.2

<問題> 7.1.3で紹介したdebuggerメソッドをSessionsコントローラのnewアクションに置いてみましょう。その後、ログアウトして /users/1/edit にアクセスしてみてください (デバッガーが途中で処理を止めるはずです)。ここでコンソールに移り、session[:forwarding_url]の値が正しいかどうか確認してみましょう。また、newアクションにアクセスしたときのrequest.get?の値も確認してみましょう (デバッガーを使っていると、ときどき予期せぬ箇所でターミナルが止まったり、おかしい挙動を見せたりします。熟練の開発者になった気になって (コラム 1.1)、落ち着いて対処してみましょう)。

<解答>

(byebug) session[:forwarding_url]
"https://rails-tutorial-******.c9users.io/users/1/edit"

正しくない。ルートが正。

(byebug) request.get?
true

演習10.3.1

演習10.3.1.1

<問題> レイアウトにあるすべてのリンクに対して統合テストを書いてみましょう。ログイン済みユーザーとそうでないユーザーのそれぞれに対して、正しい振る舞いを考えてください。ヒント: log_in_asヘルパーを使ってリスト 5.32にテストを追加してみましょう。

<解答>

[site_layout_test.rb]
require 'test_helper'

class SiteLayoutTest < ActionDispatch::IntegrationTest
  test "layout links" do
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", root_path, count: 2
    assert_select "a[href=?]", help_path
    assert_select "a[href=?]", about_path
    assert_select "a[href=?]", contact_path
    assert_select "a[href=?]", login_path
    get contact_path
    assert_select "title", full_title("Contact")
    get signup_path
    assert_select "title", full_title("Sign up")
  end
  
  def setup
    @user       = users(:michael)
  end
  
  test "layout links when logged in" do
    log_in_as(@user)
    get root_path
    assert_template 'static_pages/home'
    assert_select "a[href=?]", users_path
    assert_select "a[href=?]", user_path(@user)
    assert_select "a[href=?]", edit_user_path(@user)    
    assert_select "a[href=?]", logout_path
  end
end

演習10.3.2

演習10.3.2.1

<問題> 試しに他人の編集ページにアクセスしてみて、10.2.2で実装したようにリダイレクトされるかどうかを確かめてみましょう。

<解答> 動作確認のみなので省略。

演習10.3.3

演習10.3.3.1

<問題> Railsコンソールを開き、pageオプションにnilをセットして実行すると、1ページ目のユーザーが取得できることを確認してみましょう。

<解答>

演習10.3.3.2

<問題> 先ほどの演習課題で取得したpaginationオブジェクトは、何クラスでしょうか? また、User.allのクラスとどこが違うでしょうか? 比較してみてください。

<解答> class: User::ActiveRecord_Relation User.allと同じ。

演習10.3.4

演習10.3.4.1

<問題> 試しにリスト 10.45にあるページネーションのリンク (will_paginateの部分) を2つともコメントアウトしてみて、リスト 10.48のテストが redに変わるかどうか確かめてみましょう。

<解答> 動作確認のみなので省略。

演習10.3.4.2

<問題> 先ほどは2つともコメントアウトしましたが、1つだけコメントアウトした場合、テストが greenのままであることを確認してみましょう。will_paginateのリンクが2つとも存在していることをテストしたい場合は、どのようなテストを追加すれば良いでしょうか? ヒント: 表 5.2を参考にして、数をカウントするテストを追加してみましょう。

<解答>

[users_index_test.rb]

require 'test_helper'

class UsersIndexTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "index including pagination" do
    log_in_as(@user)
    get users_path
    assert_template 'users/index'
    assert_select 'div.pagination', count:2  <---注目
    User.paginate(page: 1).each do |user|
      assert_select 'a[href=?]', user_path(user), text: user.name
    end
  end
end

演習10.3.5

演習10.3.5.1

<問題> リスト 10.52にあるrenderの行をコメントアウトし、テストの結果が redに変わることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習10.4.1

演習10.4.1.1

<問題> Web経由でadmin属性を変更できないことを確認してみましょう。具体的には、リスト 10.56に示したように、PATCHを直接ユーザーのURL (/users/:id) に送信するテストを作成してみてください。テストが正しい振る舞いをしているかどうか確信を得るために、まずはadminをuser_paramsメソッド内の許可されたパラメータ一覧に追加するところから始めてみましょう。最初のテストの結果は redになるはずです。

<解答>

[users_controller_test.rb]

require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest

(中略)

  test "should not allow the admin attribute to be edited via the web" do
    log_in_as(@other_user)
    assert_not @other_user.admin?
    patch user_path(@other_user), params: {
                                    user: { password:              @other_user.password,
                                            password_confirmation: @other_user.password,
                                            admin: true } }
    assert_not @other_user.reload.admin?
  end
end

演習10.4.2

演習10.4.2.1

<問題> 管理者ユーザーとしてログインし、試しにサンプルユーザを2〜3人削除してみましょう。ユーザーを削除すると、Railsサーバーのログにはどのような情報が表示されるでしょうか?

<解答> 動作確認のみなので省略。

演習10.4.3

演習10.4.3.1

<問題> 試しにリスト 10.59にある管理者ユーザーのbeforeフィルターをコメントアウトしてみて、テストの結果が redに変わることを確認してみましょう

<解答> 動作確認のみなので省略。

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習9.1.1

演習9.1.1.1

<問題> コンソールを開き、データベースにある最初のユーザーを変数userに代入してください。その後、そのuserオブジェクトからrememberメソッドがうまく動くかどうか確認してみましょう。また、remember_tokenとremember_digestの違いも確認してみてください。

<解答>

>> user=User.first
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2017-02-09 07:39:54", updated_at: "2017-02-09 07:39:54", password_digest: "$2a$10$NCGVBX5axnKjyHVDxfUo5eco71WXZlmOX/9/gfBb2Gm...", remember_digest: nil>

>> user.remember
   (0.1ms)  begin transaction
  SQL (0.6ms)  UPDATE "users" SET "updated_at" = ?, "remember_digest" = ? WHERE "users"."id" = ?  [["updated_at", 2017-02-12 05:54:01 UTC], ["remember_digest", "$2a$10$DZBeoa8QGU5fxq9.stitr.SIH7uSUlLliaunThO2yWeZevK59.fge"], ["id", 1]]
   (10.2ms)  commit transaction
=> true

>> user.remember_token
=> "9jkAE-aydjad4QFuCj7TCQ"

>> user.remember_digest
=> "$2a$10$DZBeoa8QGU5fxq9.stitr.SIH7uSUlLliaunThO2yWeZevK59.fge"

演習9.1.1.1

<問題> リスト 9.3では、明示的にUserクラスを呼び出すことで、新しいトークンやダイジェスト用のクラスメソッドを定義しました。実際、User.new_tokenやUser.digestを使って呼び出せるようになったので、おそらく最も明確なクラスメソッドの定義方法であると言えるでしょう。 しかし実は、より「Ruby的に正しい」クラスメソッドの定義方法が2通りあります。1つはややわかりにくく、もう1つは非常に混乱するでしょう。テストスイートを実行して、リスト 9.4 (ややわかりにくい) や、リスト 9.5 (非常に混乱する) の実装でも、正しく動くことを確認してみてください。ヒント: selfは、通常の文脈ではUser「モデル」、つまりユーザーオブジェクトのインスタンスを指しますが、リスト 9.4やリスト 9.5の文脈では、selfはUser「クラス」を指すことにご注意ください。 わかりにくさの原因の一部はこの点にあります。

<解答> 動作確認のみなので省略。

演習9.1.2

演習9.1.2.1

<問題> ブラウザのcookieを調べ、ログイン後のブラウザではremember_tokenと暗号化されたuser_idがあることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習9.1.2.2

<問題> コンソールを開き、リスト 9.6のauthenticated?メソッドがうまく動くかどうか確かめてみましょう。

<解答> 動作確認のみなので省略。

演習9.1.3

演習9.1.3.1

<問題> ログアウトした後に、ブラウザの対応するcookiesが削除されていることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習9.1.4

演習9.1.4.1

<問題> リスト 9.16で修正した行をコメントアウトし、2つのログイン済みのタブによるバグを実際に確かめてみましょう。まず片方のタブでログアウトし、その後、もう1つのタブで再度ログアウトを試してみてください。

<解答> 動作確認のみなので省略。

演習9.1.4.2

<問題> リスト 9.19で修正した行をコメントアウトし、2つのログイン済みのブラウザによるバグを実際に確かめてみましょう。まず片方のブラウザでログアウトし、もう一方のブラウザを再起動してサンプルアプリケーションにアクセスしてみてください。

<解答> 動作確認のみなので省略。

演習9.1.4.3

<問題> 上のコードでコメントアウトした部分を元に戻し、テストスイートが red から greenになることを確認しましょう。

<解答> 動作確認のみなので省略。

演習9.2

演習9.2.1

<問題> ブラウザでcookies情報を調べ、[remember me] をチェックしたときに意図した結果になっているかどうかを確認してみましょう。

<解答> 動作確認のみなので省略。

演習9.2.2

<問題> コンソールを開き、三項演算子を使った実例を考えてみてください (コラム 9.2)。

<解答> 省略。

演習9.3.1

演習9.3.1.1

<問題> リスト 9.25の統合テストでは、仮想のremember_token属性にアクセスできないと説明しましたが、実は、assignsという特殊なテストメソッドを使うとアクセスできるようになります。コントローラで定義したインスタンス変数にテストの内部からアクセスするには、テスト内部でassignsメソッドを使用します。このメソッドにはインスタンス変数に対応するシンボルを渡します。 たとえば、createアクションで@userというインスタンス変数が定義されていれば、テスト内部ではassigns(:user)と書くことでインスタンス変数にアクセスできます。 本チュートリアルのアプリケーションの場合、Sessionsコントローラのcreateアクションでは、userを (インスタンス変数ではない) 通常のローカル変数として定義しましたが、これをインスタンス変数に変えてしまえば、cookiesにユーザーの記憶トークンが正しく含まれているかどうかをテストできるようになります。 このアイディアに従ってリスト 9.27とリスト 9.28の不足分を埋め (ヒントとして?やFILL_INを目印に置いてあります)、[remember me] チェックボックスのテストを改良してみてください。

<解答>

class SessionsController < ApplicationController

(中略)

  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    if @user && @user.authenticate(params[:session][:password])
      log_in @user
      params[:session][:remember_me] == '1' ? remember(@user) : forget(@user)
      redirect_to @user
    else
      flash.now[:danger] = 'Invalid email/password combination'
      render 'new'
    end
  end

(中略)

end

[users_login_test.rb]


(前略)

  test "login with remembering" do
    log_in_as(@user, remember_me: '1')
    assert_equal cookies['remember_token'], assigns(:user).remember_token
  end

(後略)

演習9.3.2

演習9.3.2.1

<問題> リスト 9.33にあるauthenticated?の式を削除すると、リスト 9.31の2つ目のテストで失敗することを確かめてみましょう (このテストが正しい対象をテストしていることを確認してみましょう)。

<解答> 動作確認のみなので省略。

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ

プログラミング プログラミング-Rails_チュートリアル

Ruby on Rails Tutorial最新版の演習と解答です。

f:id:mochikichi321:20170206212242p:plain

目的

Ruby on Rails チュートリアル 5.0(第4版)を学習中です。

学習を進める中で演習問題の解答がなかった(*1,2)ので、自分なりにまとめていくこととしました。

アウトプットし、自分の理解を深めることを目的としています。 もし、記載内容に誤りがあった場合はコメントいただけると幸いです。

(*1)著者による有償版の解答はあるようです。正式な解答をご希望の方はこちらを参照ください。

Learn Web Development with Rails: Michael Hartl's Ruby on Rails Tutorial | Softcover.io

(*2)旧版に関する解答はありましたが、最新版 5.0(第4版)に関しては検索しても出てきませんでした。

プログラミングを学習し始めたきっかけについてはこちら

mochikichi.hatenablog.com

演習問題と解答

演習8.1.1

演習8.1.1.1

<問題> GET login_pathとPOST login_pathとの違いを説明できますか? 少し考えてみましょう。

<解答> リスト 8.2より、

  get    '/login',   to: 'sessions#new'
  post   '/login',   to: 'sessions#create'

GET login_path: “/login"へアクセスされた際に"session#new"アクションを実行

POST login_path: “session#create"アクションの情報を”/login"へ送信

以下の「コラム 3.2. GETやその他のHTTPメソッドについて」を参照。

https://railstutorial.jp/chapters/static_pages?version=5.0#aside-get_etc

演習8.1.1.2

<問題> ターミナルのパイプ機能を使ってrails routesの実行結果とgrepコマンドを繋ぐことで、Usersリソースに関するルーティングだけを表示させることができます。同様にして、Sessionsリソースに関する結果だけを表示させてみましょう。現在、いくつのSessionsリソースがあるでしょうか? ヒント: パイプやgrepの使い方が分からない場合は Learn Enough Command Line to Be Dangerousの Section on Grep (英語) を参考にしてみてください。

<解答>

$ rails routes | grep users#
   signup GET    /signup(.:format)         users#new
    users GET    /users(.:format)          users#index
          POST   /users(.:format)          users#create
 new_user GET    /users/new(.:format)      users#new
edit_user GET    /users/:id/edit(.:format) users#edit
     user GET    /users/:id(.:format)      users#show
          PATCH  /users/:id(.:format)      users#update
          PUT    /users/:id(.:format)      users#update
          DELETE /users/:id(.:format)      users#destroy

$ rails routes | grep sessions#
    login GET    /login(.:format)          sessions#new
          POST   /login(.:format)          sessions#create
   logout DELETE /logout(.:format)         sessions#destroy

Sessionsリソースは「3つ」です。

参考:

パイプ「|」を使って 複数のコマンドを組み合わせる:http://webkaru.net/linux/commands-pipeline/

grepコマンド:https://hydrocul.github.io/wiki/commands/grep.html

演習8.1.2

演習8.1.2.1

<問題> リスト 8.4で定義したフォームで送信すると、Sessionsコントローラのcreateアクションに到達します。Railsはこれをどうやって実現しているでしょうか? 考えてみてください。ヒント:表 8.1とリスト 8.5の1行目に注目してください。

<解答> リスト8.5の1行目の以下部分で、

action="/login" method="post"

表8.1の以下のcreateアクションに到達することがわかる。 [POST /login login_path create 新しいセッションの作成 (ログイン)]

演習8.1.3

演習8.1.3.1

<問題> Railsコンソールを使って、表 8.2のそれぞれの式が合っているか確かめてみましょう. まずはuser = nilの場合を、次にuser = User.firstとした場合を確かめてみてください。ヒント: 必ず論理値オブジェクトとなるように、4.2.3で紹介した!!のテクニックを使ってみましょう。例: !!(user && user.authenticate(’foobar’))

<解答> [(nil && [オブジェクト]) == false]の確認。

>> user=nil
=> nil

>> !!(user && user.authenticate(’foobar’))
=> false

[(true && false) == false]の確認。(正しいパスワードは[123456])

>> user=User.first
  User Load (1.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2017-02-09 07:39:54", updated_at: "2017-02-09 07:39:54", password_digest: "$2a$10$NCGVBX5axnKjyHVDxfUo5eco71WXZlmOX/9/gfBb2Gm...">

>> !!(user && user.authenticate('111111'))
=> false

[(true && true) == true]の確認。(正しいパスワードは[123456])

>> !!(user && user.authenticate('123456'))
=> true

演習8.1.5

演習8.1.5.1

<問題> 8.1.4の処理の流れが正しく動いているかどうか、ブラウザで確認してみてください。特に、flashがうまく機能しているかどうか、フラッシュメッセージの表示後に違うページに移動することを忘れないでください。

<解答> 動作確認のみなので省略。

演習8.2.1

演習8.2.1.1

<問題> 有効なユーザーで実際にログインし、ブラウザからcookiesの情報を調べてみてください。このとき、sessionの値はどうなっているでしょうか? ヒント: ブラウザでcookiesを調べる方法が分からない? 今こそググってみるときです! (コラム 1.1)

<解答> f:id:mochikichi321:20170225202336p:plain

演習8.2.1.2

<問題> 先ほどの演習課題と同様に、Expiresの値について調べてみてください。

<解答> 有効期限:ブラウザセッションの終了時(演習8.2.1.1の画像参照)

演習8.2.2

演習8.2.2.1

<問題> Railsコンソールを使って、User.find_by(id: …)で対応するユーザーが検索に引っかからなかったとき、nilを返すことを確認してみましょう。

<解答>

idは1のみ存在する状態で以下を実行。id:1はtrue,id:2はnil

>> User.find_by(id:1)
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2017-02-09 07:39:54", updated_at: "2017-02-09 07:39:54", password_digest: "$2a$10$NCGVBX5axnKjyHVDxfUo5eco71WXZlmOX/9/gfBb2Gm...">

>> User.find_by(id:2)
  User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
=> nil

演習8.2.2.2

<問題> 先ほどと同様に、今度は:user_idキーを持つsessionハッシュを作成してみましょう。リスト 8.17に記したステップにしたがって、||=演算子がうまく動くことも確認してみましょう。

<解答>

>> session = {}
=> {}
>> session[:user_id] = nil
=> nil
>> @current_user ||= User.find_by(id: session[:user_id])
=> nil
>> session[:user_id]= User.first.id
=> 1
>> @current_user ||= User.find_by(id: session[:user_id])
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2017-02-09 07:39:54", updated_at: "2017-02-09 07:39:54", password_digest: "$2a$10$NCGVBX5axnKjyHVDxfUo5eco71WXZlmOX/9/gfBb2Gm...">
>> @current_user ||= User.find_by(id: session[:user_id])
=> #<User id: 1, name: "Rails Tutorial", email: "example@railstutorial.org", created_at: "2017-02-09 07:39:54", updated_at: "2017-02-09 07:39:54", password_digest: "$2a$10$NCGVBX5axnKjyHVDxfUo5eco71WXZlmOX/9/gfBb2Gm...">

演習8.2.3

演習8.2.3.1

<問題> ブラウザのcookieインスペクタ機能を使って (8.2.1.1)、セッション用のcookieを削除してみてください。ヘッダー部分にあるリンクは非ログイン状態のものになっているでしょうか? 確認してみましょう。

<解答> 動作確認のみなので省略。

演習8.2.3.2

<問題> もう一度ログインしてみて、ヘッダーのレイアウトが変わったことを確認してみましょう。その後、ブラウザを再起動させ、再び非ログイン状態に戻ったことも確認してみてください。注意: もしブラウザの [閉じたときの状態に戻す] 機能をオンにしていると、セッション情報も復元される可能性があります。もしその機能をオンにしている場合、忘れずにオフにしておきましょう (コラム 1.1)。

<解答> 動作確認のみなので省略。

演習8.2.4

演習8.2.4.1

<問題> 試しにSessionヘルパーのlogged_in?メソッドから!を削除してみて、リスト 8.23が redになることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習8.2.4.1

<問題> 先ほど削除した部分 (!) を元に戻して、テストが greenに戻ることを確認してみましょう。

<解答> 動作確認のみなので省略。

演習8.2.5

演習8.2.5.1

<問題> リスト 8.25のlog_inの行をコメントアウトすると、テストスイートは red になるでしょうか? それとも green になるでしょうか? 確認してみましょう。

<解答> RED

演習8.2.5.2

<問題> 現在使用しているテキストエディタの機能を使って、リスト 8.25をまとめてコメントアウトできないか調べてみましょう。また、コメントアウトの前後でテストスイートを実行し、コメントアウトすると red に、コメントアウトを元に戻すと green になることを確認してみましょう。ヒント: コメントアウト後にファイルを保存することを忘れないようにしましょう。また、テキストエディタコメントアウト機能については Test Editor Tutorial の Commenting Out (英語) などを参照してみてください。

<解答> 動作確認のみなので省略。

演習8.3

演習8.3.1

<問題> ブラウザから [Log out] リンクをクリックし、どんな変化が起こるか確認してみましょう。また、リスト 8.31で定義した3つのステップを実行してみて、うまく動いているかどうか確認してみましょう。

<解答> 動作確認のみなので省略。

演習8.3.2

<問題> cookiesの内容を調べてみて、ログアウト後にはsessionが正常に削除されていることを確認してみましょう。

<解答> 動作確認のみなので省略。

関連記事

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com