新米パパの育児留学

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

新米パパの育児留学

『育児留学』とは、育児を通して異なる視点を得たり新しいことに挑戦して自己成長に繋げること。育児奮闘中の新米パパが育児を通して得た気づきや感じたこと、育休中に習得したプログラミングに関する話題を発信していきます。

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

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

演習問題と解答

演習7.1.1

演習7.1.1.1

<問題> ブラウザから /about にアクセスし、デバッグ情報が表示されていることを確認してください。このページを表示するとき、どのコントローラとアクションが使われていたでしょうか? paramsの内容から確認してみましょう。

<解答> 以下のデバッグ情報が表示されます。 “static_pages"コントローラーの"about"アクションが実行された。

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: static_pages
  action: about
permitted: false

演習7.1.1.2

<問題> Railsコンソールを開き、データベースから最初のユーザー情報を取得し、変数userに格納してください。その後、puts user.attributes.to_yamlを実行すると何が表示されますか? ここで表示された結果と、yメソッドを使ったy user.attributesの実行結果を比較してみましょう。

<解答> 実行結果は以下の通り。 “puts user.attributes.to_yaml"の実行結果と"y user.attributes"の実行結果は同じです。

>> user=User.first
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
=> #<User id: 1, name: "Yamada", email: "mhartl@example.com", created_at: "2017-02-05 02:01:37", updated_at: "2017-02-05 02:36:54", password_digest: "$2a$10$E.gAC.d0Ch5dvmrM6vnNhu6gIpNtwFD8JhHmKPyc/V3...">

>> puts user.attributes.to_yaml
---
id: 1
name: Yamada
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2017-02-05 02:01:37.355601000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2017-02-05 02:36:54.834356000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$E.gAC.d0Ch5dvmrM6vnNhu6gIpNtwFD8JhHmKPyc/V3u1di9B67dO"
=> nil

>> y user.attributes
---
id: 1
name: Yamada
email: mhartl@example.com
created_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &1 2017-02-05 02:01:37.355601000 Z
  zone: &2 !ruby/object:ActiveSupport::TimeZone
    name: Etc/UTC
  time: *1
updated_at: !ruby/object:ActiveSupport::TimeWithZone
  utc: &3 2017-02-05 02:36:54.834356000 Z
  zone: *2
  time: *3
password_digest: "$2a$10$E.gAC.d0Ch5dvmrM6vnNhu6gIpNtwFD8JhHmKPyc/V3u1di9B67dO"
=> nil

演習7.1.2

演習7.1.2.1

<問題> 埋め込みRubyを使って、マジックカラム (created_atとupdated_at) の値をshowページに表示してみましょう (リスト 7.4)。

<解答>

<%= @user.name %>, <%= @user.email %>, <%= @user.created_at %>, <%= @user.updated_at %>

f:id:mochikichi321:20170219201416p:plain

演習7.1.2.2

<問題> 埋め込みRubyを使って、Time.nowの結果をshowページに表示してみましょう。ページを更新すると、その結果はどう変わっていますか? 確認してみてください。

<解答>

<%= @user.name %>, <%= @user.email %>, <%= @user.created_at %>, <%= @user.updated_at %>,
<%= Time.now %>

f:id:mochikichi321:20170219201506p:plain

更新すると表示時間も更新されます。

演習7.1.3

演習7.1.3.1

<問題> showアクションの中にdebuggerを差し込み (リスト 7.6)、ブラウザから /users/1 にアクセスしてみましょう。その後コンソールに移り、putsメソッドを使ってparamsハッシュの中身をYAML形式で表示してみましょう。ヒント: 7.1.1.1の演習を参考にしてください。その演習ではdebugメソッドで表示したデバッグ情報を、どのようにしてYAML形式で表示していたでしょうか?

<解答>

(byebug) a=params
<ActionController::Parameters {"controller"=>"users", "action"=>"show", "id"=>"1"} permitted: false>

(byebug) puts a.to_yaml
--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  controller: users
  action: show
  id: '1'
permitted: false
nil

7.1.1.1の演習に関して、 debugヘルパーは、YAMLフォーマットを使ったオブジェクトを描画した\<pre>タグを返します。

演習7.1.3.2

<問題> newアクションの中にdebuggerを差し込み、/users/new にアクセスしてみましょう。@userの内容はどのようになっているでしょうか? 確認してみてください。

<解答>

(byebug) @user
nil

演習7.1.4

演習7.1.4.1

<問題> (任意) Gravatar上にアカウントを作成し、あなたのメールアドレスと適当な画像を紐付けてみてください。メールアドレスをMD5ハッシュ化して、紐付けた画像がちゃんと表示されるかどうか試してみましょう。

<解答> 省略

演習7.1.4.2

<問題> 7.1.4で定義したgravatar_forヘルパーをリスト 7.12のように変更して、sizeをオプション引数として受け取れるようにしてみましょう。うまく変更できると、gravatar_for user, size: 50といった呼び出し方ができるようになります。重要: この改善したヘルパーは10.3.1で実際に使います。忘れずに実装しておきましょう。

<解答> リスト7.12参照。

演習7.1.4.3

<問題> オプション引数は今でもRubyコミュニティで一般的に使われていますが、Ruby 2.0から導入された新機能「キーワード引数 (Keyword Arguments)」でも実現することができます。先ほど変更したリスト 7.12を、リスト 7.13のように置き換えてもうまく動くことを確認してみましょう。この2つの実装方法はどういった違いがあるのでしょうか? 考えてみてください。

<解答> 動作確認のみなので省略。 オプション引数よりもキーワード引数の方が簡潔に実装できる。

演習7.2.1

演習7.2.1.1

<問題> 試しに、リスト 7.15にある:nameを:nomeに置き換えてみましょう。どんなエラーメッセージが表示されるようになりますか?

<解答> undefined method `nome'

演習7.2.1.2

<問題> 試しに、ブロックの変数fをすべてfoobarに置き換えてみて、結果が変わらないことを確認してみてください。確かに結果は変わりませんが、変数名をfoobarとするのはあまり良い変更ではなさそうですね。その理由について考えてみてください。

<解答> 変数fは “form” のfを使用している。 “f.label"等がHTMLフォーム要素に対応することがわかるようにする。 "foobar"はメタ構文変数(意味を持たない名前)として認識されるため適さない。

演習7.2.2

演習7.2.2.1

<問題> Learn Enough HTML to Be DangerousではHTMLをすべて手動で書き起こしていますが、なぜformタグを使わなかったのでしょうか? 理由を考えてみてください。

<解答> formタグは、入力・送信フォームを作成するために使用される。 本文中では、入力・送信が必要ないので使用していない。 (ログインページにはformタグが使用されています。)

演習7.3.2

演習7.3.2.1

<問題> /users/new?admin=1 にアクセスし、paramsの中にadmin属性が含まれていることをデバッグ情報から確認してみましょう。

<解答>

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  admin: '1'
  controller: users
  action: new
permitted: false

演習7.3.3

演習7.3.3.1

<問題> 最小文字数を5に変更すると、エラーメッセージも自動的に更新されることを確かめてみましょう。

<解答>

[user.rb]


class User < ApplicationRecord
(中略)
  validates :password, presence: true, length: { minimum: 5 }  
end

f:id:mochikichi321:20170219201509p:plain

演習7.3.3.2

<問題> 未送信のユーザー登録フォーム (図 7.12) のURLと、送信済みのユーザー登録フォーム (図 7.18) のURLを比べてみましょう。なぜURLは違っているのでしょうか? 考えてみてください。

<解答> 未送信のユーザー登録フォーム (図 7.12) のURLは以下。 “・・・/signup”

ルーティングの以下が実行されている。

[routes.rb]

(前略)
  get '/signup',    to: 'users#new'
(後略)

送信済みのユーザー登録フォーム (図 7.18) のURLは以下。 “・・・/users”

ルーティングの以下が実行されている。

[routes.rb]

(前略)
  resources :users
(後略)

これは、表7.1のルートを指し、その中の"ユーザーを作成するアクション"が実行されている。

  post '/users'  'users#create'

演習7.3.4

演習7.3.4.1

<問題> リスト 7.20で実装したエラーメッセージに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.25にテンプレートを用意しておいたので、参考にしてください。

<解答>

[users_signup_test.rb]

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path

(中略)

    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.alert'   
  end
end

演習7.3.4.2

<問題> 未送信のユーザー登録フォームと送信直後のURLは、それぞれ /signup と /users になり、URLが異なっています。これは、リスト 5.43で追加した名前付きルートと、デフォルトのRESTfulなルーティング (リスト 7.3) を設定したことによって生じた差異です。リスト 7.26とリスト 7.27の内容を追加し、この問題を解決してみてください。うまくいけば、いずれのURLも /signup となるはずです。あれ、でもテストは greenのままになっていますね…、なぜでしょうか? (考えてみてください)

<解答> リスト7.26とリスト7.27の内容を追加すると、いずれのURLも /signup となる。 GREENのままとなっている理由は演習7.3.4.3及び演習7.3.4.4参照。

演習7.3.4.3

<問題> リスト 7.25のpost部分を変更して、上の演習課題で作られた新しいURLに合わせてみましょう。また、テストが依然として greenのままになっている点も確認してください。

<解答>

[users_signup_test.rb]

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post signup_path, params: { user: { name:  "",
(後略)

テストはGREEN。

演習7.3.4.4

<問題> リスト 7.27のフォームを以前の状態 (リスト 7.20) に戻してみて、テストがやはり greenになっていることを確認してください。これは問題です! なぜなら、現在postが送信されているURLは正しくないのですから。assert_selectを使ったテストをリスト 7.25に追加し、このバグを検知できるようにしてみましょう (テストを追加して redになれば成功です)。その後、変更後のフォーム (リスト 7.27) に戻してみて、テストが green になることを確認してみましょう。ヒント: フォームから送信してテストするのではなく、’form[action=“/signup”]’という部分が存在するかどうかに着目してテストしてみましょう。

<解答> リスト 7.27のフォームを以前の状態 (リスト 7.20) に戻してもテストはGREEN。

テストを以下の通りとするとテストはRED。

[users_signup_test.rb]

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do

(中略)

    assert_select 'form[action="/signup"]'
  end
end

リスト7.27に戻してテストするとGREEN。

演習7.4.1

演習7.4.1.1

<問題> 有効な情報を送信し、ユーザーが実際に作成されたことを、Railsコンソールを使って確認してみましょう。

<解答> 以下のユーザー情報を送信

f:id:mochikichi321:20170219201516p:plain

二人目のユーザー情報が作成されました。(表示のさせ方はいろいろあります。)

>> User.second
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ? OFFSET ?  [["LIMIT", 1], ["OFFSET", 1]]
=> #<User id: 2, name: "Yamada", email: "yamada@mail.com", created_at: "2017-02-09 06:56:06", updated_at: "2017-02-09 06:56:06", password_digest: "$2a$10$0JljS52iRoEmJQ5uhNbnVeDc9/cAuYWtKrMmour10cG...">

演習7.4.1.2

<問題> リスト 7.28を更新し、redirect_to user_url(@user)とredirect_to @userが同じ結果になることを確認してみましょう。

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

演習7.4.2

演習7.4.2.1

<問題> コンソールに移り、文字列内の式展開 (4.2.2) でシンボルを呼び出してみましょう。例えば"#{:success}“といったコードを実行すると、どんな値が返ってきますか? 確認してみてください。

<解答>

>> "#{:success}"
=> "success"

演習7.4.2.2

<問題> 先ほどの演習で試した結果を参考に、リスト 7.30のflashはどのような結果になるか考えてみてください。

<解答>

>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", :danger=>"It failed."}

>> "#{flash[:success]}"
=> "It worked!"

>> "#{flash[:danger]}"
=> "It failed."

演習7.4.3

演習7.4.3.1

<問題> Railsコンソールを使って、新しいユーザーが本当に作成されたのかもう一度チェックしてみましょう。結果は、リスト 7.32のようになるはずです。

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

演習7.4.3.2

<問題> 自分のメールアドレスでユーザー登録を試してみましょう。既にGravatarに登録している場合、適切な画像が表示されているか確認してみてください。

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

演習7.4.4

演習7.4.4.1

<問題> 7.4.2で実装したflashに対するテストを書いてみてください。どのくらい細かくテストするかはお任せします。リスト 7.34に最小限のテンプレートを用意しておいたので、参考にしてください (FILL_INの部分を適切なコードに置き換えると完成します)。ちなみに、テキストに対するテストは壊れやすいです。文量の少ないflashのキーであっても、それは同じです。筆者の場合、flashが空でないかをテストするだけの場合が多いです。

<解答>

[users_signup_test.rb]

require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

(中略)
  
  test "valid signup information" do
(中略)
    assert_not flash.empty?    
  end  
end

演習7.4.4.2

<問題> 本文中でも指摘しましたが、flash用のHTML (リスト 7.31) は読みにくいです。より読みやすくしたリスト 7.35のコードに変更してみましょう。変更が終わったらテストスイートを実行し、正常に動作することを確認してください。なお、このコードでは、Railsのcontent_tagというヘルパーを使っています。

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

演習7.4.4.3

<問題> リスト 7.28のリダイレクトの行をコメントアウトすると、テストが失敗することを確認してみましょう。

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

演習7.4.4.4

<問題> リスト 7.28で、@user.saveの部分をfalseに置き換えたとしましょう (バグを埋め込んでしまったと仮定してください)。このとき、assert_differenceのテストではどのようにしてこのバグを検知するでしょうか? テストコードを追って考えてみてください。

<解答> 以下のテストでは、assert_differenceブロック内の処理を実行する直前と、実行した直後のUser.countの値を比較し、1増えた際にtrueとなる。@user.saveが実行されないことによって、User.countは増えないためerrorとなる。

assert_difference 'User.count', 1 do
  post users_path, ...
end

演習7.5.3

演習7.5.3.1

<問題> ブラウザから本番環境 (Heroku) にアクセスし、SSLの鍵マークがかかっているか、URLがhttpsになっているかどうかを確認してみましょう。

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

演習7.5.3.1

<問題> 本番環境でユーザーを作成してみましょう。Gravatarの画像は正しく表示されているでしょうか?

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

関連記事

【第1章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第2章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第3章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第4章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第5章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第6章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第14章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

Rails 検索機能拡張 (rails tutorial) - 新米パパの育児留学

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。

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

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

演習問題と解答

演習6.1.1

演習6.1.1.1

<問題> Railsはdb/ディレクトリの中にあるschema.rbというファイルを使っています。これはデータベースの構造 (スキーマ (schema) と呼びます) を追跡するために使われます。さて、あなたの環境にあるdb/schema.rbの内容を調べ、その内容とマイグレーションファイル (リスト 6.2) の内容を比べてみてください。

<解答>

[schema.rb]

ActiveRecord::Schema.define(version: 20170203234505) do

  create_table "users", force: :cascade do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

[20170203234505_create_users.rb]

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end

異なる点は以下の2つ。

①「created_at,updated_at」と「t.timestamps」 ⇒本文中に「t.timestampsは特別なコマンドで、created_atとupdated_atという2つの「マジックカラム (Magic Columns)」を作成します。」とあるので、実質構成は同じ。

②「create_table」に対して「force: :cascade」の有無 ⇒「force: :cascade」:外部キーが適切であればスキーマが再読み込みできるようになります。(参照元https://railsguides.jp/4_2_release_notes.html

ないとどうなるのかは現時点ではわからない。。。

演習6.1.1.2

<問題> ほぼすべてのマイグレーションは、元に戻すことが可能です (少なくとも本チュートリアルにおいてはすべてのマイグレーションを元に戻すことができます)。元に戻すことを「ロールバック (rollback)と呼び、Railsではdb:rollbackというコマンドで実現できます。

  $ rails db:rollback

上のコマンドを実行後、db/schema.rbの内容を調べてみて、ロールバックが成功したかどうか確認してみてください (コラム 3.1ではマイグレーションに関する他のテクニックもまとめているので、参考にしてみてください)。 上のコマンドでは、データベースからusersテーブルを削除するためにdrop_tableコマンドを内部で呼び出しています。 これがうまくいくのは、drop_tableとcreate_tableがそれぞれ対応していることをchangeメソッドが知っているからです。この対応関係を知っているため、ロールバック用の逆方向のマイグレーションを簡単に実現することができるのです。なお、あるカラムを削除するような不可逆なマイグレーションの場合は、changeメソッドの代わりに、upとdownのメソッドを別々に定義する必要があります。 詳細については、Railsガイドの「Active Record マイグレーション」を参照してください。

<解答> 指示通り以下を実行

  $ rails db:rollback

[schema.rb]

ActiveRecord::Schema.define(version: 0) do

end

ロールバック完了。

演習6.1.1.3

<問題> もう一度rails db:migrateコマンドを実行し、db/schema.rbの内容が元に戻ったことを確認してください。

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

演習6.1.2

演習6.1.2.1

<問題> Railsコンソールを開き、User.newでUserクラスのオブジェクトが生成されること、そしてそのオブジェクトがApplicationRecordを継承していることを確認してみてください (ヒント: 4.4.4で紹介したテクニックを使ってみてください)。

<解答>

>> User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
>> User.superclass
=> ApplicationRecord(abstract)

演習6.1.2.2

<問題> 同様にして、ApplicationRecordがActiveRecord::Baseを継承していることについて確認してみてください。

<解答>

>> ApplicationRecord.superclass
=> ActiveRecord::Base

演習6.1.3

演習6.1.3.1

<問題> user.nameとuser.emailが、どちらもStringクラスのインスタンスであることを確認してみてください。

<解答>

>> user.name.class
=> String

>> user.email.class
=> String

演習6.1.3.2

<問題> created_atとupdated_atは、どのクラスのインスタンスでしょうか?

<解答>

>> user.created_at.class
=> ActiveSupport::TimeWithZone

>> user.updated_at.class
=> ActiveSupport::TimeWithZone

演習6.1.4

演習6.1.4.1

<問題> nameを使ってユーザーオブジェクトを検索してみてください。また、 find_by_nameメソッドが使えることも確認してみてください (古いRailsアプリケーションでは、古いタイプのfind_byをよく見かけることでしょう)。

<解答>

>> User.find_by(name: "Michael Hartl")
  User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "Michael Hartl"], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2017-02-04 05:46:02", updated_at: "2017-02-04 05:46:02">

>> User.find_by_name("Michael Hartl")                                                                            
  User Load (0.1ms)  SELECT  "users".* FROM "users" WHERE "users"."name" = ? LIMIT ?  [["name", "Michael Hartl"], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2017-02-04 05:46:02", updated_at: "2017-02-04 05:46:02">

演習6.1.4.2

<問題> 実用的な目的のため、User.allはまるで配列のように扱うことができますが、実際には配列ではありません。 User.allで生成されるオブジェクトを調べ、ArrayクラスではなくUser::ActiveRecord_Relationクラスであることを確認してみてください。

<解答>

>> User.all.class
=> User::ActiveRecord_Relation

演習6.1.4.3

<問題> User.allに対してlengthメソッドを呼び出すと、その長さを求められることを確認してみてください (4.2.3)。

<解答>

>> User.all.length
  User Load (0.3ms)  SELECT "users".* FROM "users"
=> 2

演習6.1.5

演習6.1.5.1

<問題> userオブジェクトへの代入を使ってname属性を使って更新し、saveで保存してみてください。

<解答>

>> user.name="Taro Yamada"
=> "Taro Yamada"
>> user.save
   (0.2ms)  SAVEPOINT active_record_1
  SQL (1.1ms)  UPDATE "users" SET "updated_at" = ?, "name" = ? WHERE "users"."id" = ?  [["updated_at", 2017-02-04 06:34:26 UTC], ["name", "Taro Yamada"], ["id", 1]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

演習6.1.5.2

<問題> 今度はupdate_attributes(*)を使って、email属性を更新および保存してみてください。

<解答>

>> user.update_attribute(:email,"yamada@mail.com")
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.1ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["email", "yamada@mail.com"], ["updated_at", 2017-02-04 06:37:31 UTC], ["id", 1]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
=> true

>> user.email
=> "yamada@mail.com"

*問題では「update_attributes」となっていますが、最後の「s」は不要です。

演習6.1.5.3

<問題> 同様にして、マジックカラムであるcreated_atも直接更新できることを確認してみてください。ヒント: 更新するときは「1.year.ago」を使うと便利です。これはRails流の時間指定の1つで、現在の時刻から1年前の時間を算出してくれます。

<解答>

>> user.update_attribute(:created_at,1.year.ago)
   (0.1ms)  SAVEPOINT active_record_1
  SQL (0.2ms)  UPDATE "users" SET "created_at" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["created_at", 2016-02-04 06:43:54 UTC], ["updated_at", 2017-02-04 06:42:00 UTC], ["id", 1]]
   (0.0ms)  RELEASE SAVEPOINT active_record_1
=> true

>> user.created_at
=> Thu, 04 Feb 2016 06:43:54 UTC +00:00

演習6.2.1

演習6.2.1.1

<問題> コンソールから、新しく生成したuserオブジェクトが有効 (valid) であることを確認してみましょう。

<解答>

>> user=User.new(name:"Taro Yamada")                                                                              
=> #<User id: nil, name: "Taro Yamada", email: nil, created_at: nil, updated_at: nil>

>> user.valid?
=> true

演習6.2.1.2

<問題> 6.1.3で生成したuserオブジェクトも有効であるかどうか、確認してみましょう。

<解答>

>> User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

>> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
=> #<User id: nil, name: "Michael Hartl", email: "mhartl@example.com", created_at: nil, updated_at: nil>

>> user.valid?
=> true

演習6.2.2

演習6.2.2.1

<問題> 新しいユーザーuを作成し、作成した時点では有効ではない (invalid) ことを確認してください。なぜ有効ではないのでしょうか? エラーメッセージを確認してみましょう。

<解答>

>> u=User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

>> u.valid?
=> false

>> u.errors.full_messages
=> ["Name can't be blank", "Email can't be blank"]

演習6.2.2.2

<問題> u.errors.messagesを実行すると、ハッシュ形式でエラーが取得できることを確認してください。emailに関するエラー情報だけを取得したい場合、どうやって取得すれば良いでしょうか?

<解答>

>> u.errors.messages
=> {:name=>["can't be blank"], :email=>["can't be blank"]}

>> u.errors.messages[:email]
=> ["can't be blank"]

演習6.2.3

演習6.2.3.1

<問題> 長すぎるnameとemail属性を持ったuserオブジェクトを生成し、有効でないことを確認してみましょう。

<解答>

>> user=User.new(name:"123456789012345678901234567890123456789012345678901",email:"1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890@mail.com")
=> #<User id: nil, name: "12345678901234567890123456789012345678901234567890...", email: "12345678901234567890123456789012345678901234567890...", created_at: nil, updated_at: nil>

>> user.valid?
=> false

演習6.2.3.2

<問題> 長さに関するバリデーションが失敗した時、どんなエラーメッセージが生成されるでしょうか? 確認してみてください。

<解答>

>> user.errors.full_messages
=> ["Name is [f:id:mochikichi321:20170218200721p:plain][f:id:mochikichi321:20170218200723p:plain]too long (maximum is 50 characters)", "Email is too long (maximum is 255 characters)"]

演習6.2.4

演習6.2.4.1

<問題> リスト 6.18にある有効なメールアドレスのリストと、リスト 6.19にある無効なメールアドレスのリストをRubularのYour test string:に転記してみてください。その後、リスト 6.21の正規表現をYour regular expression:に転記して、有効なメールアドレスのみがすべてマッチし、無効なメールアドレスはすべてマッチしないことを確認してみましょう。

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

演習6.2.4.2

<問題> 先ほど触れたように、リスト 6.21のメールアドレスチェックする正規表現は、foo@bar..comのようにドットが連続した無効なメールアドレスを許容してしまいます。まずは、このメールアドレスをリスト 6.19の無効なメールアドレスリストに追加し、これによってテストが失敗することを確認してください。次に、リスト 6.23で示した、少し複雑な正規表現を使ってこのテストがパスすることを確認してください。 <解答> “foo@bar..com"を追加。

[user_test.rb]

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    @user = User.new(name: "Example User", email: "user@example.com")
  end

(中略)

  test "email validation should reject invalid addresses" do
    invalid_addresses = %w[user@example,com user_at_foo.org user.name@example.
                           foo@bar_baz.com foo@bar+baz.com foo@bar..com]
    invalid_addresses.each do |invalid_address|
      @user.email = invalid_address
      assert_not @user.valid?, "#{invalid_address.inspect} should be invalid"
    end
  end 
end

テスト結果はRED。 リスト 6.23のとおり修正してテストすると、GREEN。

演習6.2.4.3

<問題> foo@bar..comをRubularのメールアドレスのリストに追加し、リスト 6.23の正規表現をRubularで使ってみてください。有効なメールアドレスのみがすべてマッチし、無効なメールアドレスはすべてマッチしないことを確認してみましょう。

<解答>

f:id:mochikichi321:20170218200723p:plain

演習6.2.5

演習6.2.5.1

<問題> リスト 6.33を参考に、メールアドレスを小文字にするテストをリスト 6.32に追加してみましょう。ちなみに追加するテストコードでは、データベースの値に合わせて更新するreloadメソッドと、値が一致しているかどうか確認するassert_equalメソッドを使っています。リスト 6.33のテストがうまく動いているか確認するためにも、before_saveの行をコメントアウトして redになることを、また、コメントアウトを解除すると greenになることを確認してみましょう。

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

演習6.2.5.2

<問題> テストスイートの実行結果を確認しながら、before_saveコールバックをemail.downcase!に書き換えてみましょう。ヒント: メソッドの末尾に!を付け足すことにより、email属性を直接変更できるようになります (リスト 6.34)。

<解答> リスト6.34参照。

演習6.3.2

演習6.3.2.1

<問題> この時点では、userオブジェクトに有効な名前とメールアドレスを与えても、valid?で失敗してしまうことを確認してみてください。

<解答>

>> user=User.new(name:"Taro Yamada",email:"yamada@mail.com")
=> #<User id: nil, name: "Taro Yamada", email: "yamada@mail.com", created_at: nil, updated_at: nil, password_digest: nil>

>> user.valid?
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "yamada@mail.com"], ["LIMIT", 1]]
=> false

演習6.3.2.2

<問題> なぜ失敗してしまうのでしょうか? エラーメッセージを確認してみてください。

<解答>

>> user.errors.full_messages
=> ["Password can't be blank"]

演習6.3.3

演習6.3.3.1

<問題> 有効な名前とメールアドレスでも、パスワードが短すぎるとuserオブジェクトが有効にならないことを確認してみましょう。

<解答>

>> user=User.new(name:"Taro Yamada",email:"yamada@mail.com",password:"12345")
=> #<User id: nil, name: "Taro Yamada", email: "yamada@mail.com", created_at: nil, updated_at: nil, password_digest: "$2a$10$W699oKChtVu6Hd2D4uDSsOb9KI6i0HiDcNvobt7xhfW...">

>> user.valid?
  User Exists (0.3ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) LIMIT ?  [["email", "yamada@mail.com"], ["LIMIT", 1]]
=> false

演習6.3.3.2

<問題> 上で失敗した時、どんなエラーメッセージになるでしょうか? 確認してみましょう。

<解答>

>> user.errors.full_messages
=> ["Password is too short (minimum is 6 characters)"]

演習6.3.4

演習6.3.4.1

<問題> コンソールを一度再起動して (userオブジェクトを消去して)、このセクションで作ったuserオブジェクトを検索してみてください。

<解答>

>> user = User.find_by(email: "mhartl@example.com")
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."email" = ? LIMIT ?  [["email", "mhartl@example.com"], ["LIMIT", 1]]
=> #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2017-02-05 02:01:37", updated_at: "2017-02-05 02:01:37", password_digest: "$2a$10$E.gAC.d0Ch5dvmrM6vnNhu6gIpNtwFD8JhHmKPyc/V3...">

演習6.3.4.2

<問題> オブジェクトが検索できたら、名前を新しい文字列に置き換え、saveメソッドで更新してみてください。うまくいきませんね…、なぜうまくいかなかったのでしょうか?

<解答>

>> user.name="Yamada"
=> "Yamada"

>> user.save
   (0.2ms)  begin transaction
  User Exists (0.2ms)  SELECT  1 AS one FROM "users" WHERE LOWER("users"."email") = LOWER(?) AND ("users"."id" != ?) LIMIT ?  [["email", "mhartl@example.com"], ["id", 1], ["LIMIT", 1]]
   (0.1ms)  rollback transaction
=> false

name属性を変更し、.saveを実行すると、変更していない箇所も全て保存を要求される。 すなわち、パスワードをレコードに保存することを要求するため、エラーが生じる。 変更及び保存をname属性のみに限定する必要がある。(6.3.4.3参照)

演習6.3.4.3

<問題> 今度は6.1.5で紹介したテクニックを使って、userの名前を更新してみてください。

<解答>

>> user.update_attribute(:name, "Yamada")
   (0.1ms)  begin transaction
  SQL (0.4ms)  UPDATE "users" SET "name" = ?, "updated_at" = ? WHERE "users"."id" = ?  [["name", "Yamada"], ["updated_at", 2017-02-05 02:36:54 UTC], ["id", 1]]
   (10.0ms)  commit transaction
=> true

“updated_at"が更新されており、保存がうまくいったことがわかる。

関連記事

【第1章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第2章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第3章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第4章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第5章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第7章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第14章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

Rails 検索機能拡張 (rails tutorial) - 新米パパの育児留学

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。

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

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

演習問題と解答

演習5.1.1

演習5.1.1.1

<問題> Webページと言ったらネコ画像、というぐらいにはWebにはネコ画像が溢れていますよね。リスト 5.4のコマンドを使って、図 5.3のネコ画像をダウンロードしてきましょう。

<解答> 省略。

演習5.1.1.2

<問題> mvコマンドを使って、ダウンロードしたkitten.jpgファイルを適切なアセットディレクトリに移動してください (参考: 5.2.1)。

<解答>

$ mv kitten.jpg app/assets/images/

演習5.1.1.3

<問題> image_tagを使って、kitten.jpg画像を表示してみてください (図 5.4)。

<解答>

<%= image_tag("kitten.jpg") %>

演習5.1.2

演習5.1.2.1

<問題> リスト 5.10を参考にして、5.1.1.1で使ったネコ画像をコメントアウトしてみてください。また、ブラウザのHTMLインスペクタ機能を使って、コメントアウトするとHTMLのソースからも消えていることを確認してみてください。

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

演習5.1.2.2

<問題> リスト 5.11のコードをcustom.scssに追加し、すべての画像を非表示にしてみてください。うまくいけば、Railsのロゴ画像がHomeページから消えるはずです。先ほどと同様にインスペクタ機能を使って、今度はHTMLのソースコードは残ったままで、画像だけが表示されなくなっていることを確認してみてください。

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

演習5.1.3

演習5.1.3.1

<問題> Railsがデフォルトで生成するheadタグの部分を、リスト 5.18のようにrenderに置き換えてみてください。ヒント: 単純に削除してしまうと後でパーシャルを1から書き直す必要が出てくるので、削除する前にどこかに退避しておきましょう。

<解答>

[_rails_default.html.erb]

<%= csrf_meta_tags %>
<%= stylesheet_link_tag 'application', media: 'all',
'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>

[application.html.erb]

(前略)
<head>
 <title><%= full_title(yield(:title)) %></title>
 <%= render 'layouts/rails_default' %>
 <%= render 'layouts/shim' %>
</head>
(後略)

演習5.1.3.2

<問題> リスト 5.18のようなパーシャルはまだ作っていないので、現時点ではテストは redになっているはずです。実際にテストを実行して確認してみましょう。

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

演習5.1.3.3

<問題> layoutsディレクトリにheadタグ用のパーシャルを作成し、先ほど退避しておいたコードを書き込み、最後にテストが green に戻ることを確認しましょう。

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

演習5.2.1

演習5.2.1.1

<問題> 5.2.2で提案したように、footerのCSSを手作業で変換してみましょう。具体的には、リスト 5.17の内容を1つずつ変換していき、リスト 5.20のようにしてみてください。

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

演習5.3.2

演習5.3.2.1

<問題> 実は名前付きルートは、as:オプションを使って変更することができます。有名なFar Sideの漫画に倣って、Helpページの名前付きルートをhelfに変更してみてください。

<解答>

[static_pages_controller_test.rb]

test "should get help" do
  get helf_path
  assert_response :success
  assert_select "title", "Help | #{@base_title}"
end

演習5.3.2.2

<問題> 先ほどの変更により、テストが redになっていることを確認してください。リスト 5.28を参考にルーティングを更新して、テストを greenにして見てください。

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

演習5.3.2.3

<問題> エディタのUndo機能を使って、今回の演習で行った変更を元に戻して見てください。

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

演習5.3.3

演習5.3.3.1

<問題> リスト 5.29のようにhelfルーティングを作成し、レイアウトのリンクを更新してみてください。

<解答>

[routes.rb]

Rails.application.routes.draw do
(中略)
  get '/help', to: 'static_pages#help', as: 'helf'
(中略)
end

[_header.html.erb]

(前略)
<li><%= link_to "Help", helf_path %></li>
(後略)

演習5.3.3.2

<問題> 前回の演習と同様に、エディタのUndo機能を使ってこの演習で行った変更を元に戻してみてください。

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

演習5.3.4

演習5.3.4.1

<問題> footerパーシャルのabout_pathをcontact_pathに変更してみて、テストが正しくエラーを捕まえてくれるかどうか確認してみてください。

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

演習5.3.4.2

<問題> リスト 5.35で示すように、Applicationヘルパーで使っているfull_titleヘルパーを、test環境でも使えるようにすると便利です。こうしておくと、リスト 5.36のようなコードを使って、正しいタイトルをテストすることができます。ただし、これは完璧なテストではありません。たとえばベースタイトルに「Ruby on Rails Tutoial」といった誤字があったとしても、このテストでは発見することができないでしょう。この問題を解決するためには、full_titleヘルパーに対するテストを書く必要があります。そこで、Applicationヘルパーをテストするファイルを作成し、リスト 5.37のFILL_INの部分を適切なコードに置き換えてみてください。ヒント: リスト 5.37ではassert_equal <期待される値>, <実際の値>といった形で使っていましたが、内部では==演算子で期待される値と実際の値を比較し、正しいかどうかのテストをしています。

<解答> まず、リスト 5.35,5.36をガイドどおり修正。ベースタイトルに「Ruby on Rails Tutoial」といった誤字があった場合、エラーが出るか確認。

[application_helper_test]

module ApplicationHelper

 # ページごとの完全なタイトルを返します。 # コメント行
  def full_title(page_title = '') # メソッド定義とオプション引数
    base_title = "Ruby on Rails Tutoial Sample App" # 変数への代入
    if page_title.empty? # 論理値テスト
      base_title # 暗黙の戻り値
    else
      page_title + " | " + base_title # 文字列の結合
    end
  end
end

テスト結果はGREEN。エラー出ません。

次に、リスト5.37に従って、test作成

[application_helper_test.rb]

require 'test_helper'

class ApplicationHelperTest < ActionView::TestCase
  test "full title helper" do
    assert_equal full_title, "Ruby on Rails Tutorial Sample App"
    assert_equal full_title("Help"), "Help | Ruby on Rails Tutorial Sample App"
  end
end

テスト結果はRED。エラー出ました。

最後に、脱字を直して再度テスト。結果はGREEN。

演習5.4.1

演習5.4.1.1

<問題> 表 5.1を参考にしながらリスト 5.41を変更し、users_new_urlではなくsignup_pathを使えるようにしてみてください。

[users_controller_test.rb]

require 'test_helper'

class UsersControllerTest < ActionDispatch::IntegrationTest
  test "should get new" do
    get signup_path
    assert_response :success
  end
end

演習5.4.1.2

<問題> 先ほどの変更を加えたことにより、テストが redになったことを確認してください。なお、この演習はテスト駆動開発 (コラム 3.3) で説明した red/green のリズムを作ることを目的としています。このテストは次の5.4.2で greenになるよう修正します。

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

演習5.4.2

演習5.4.2.1

<問題> もしまだ5.4.1.1の演習に取り掛かっていなければ、まずはリスト 5.41のように変更し、名前付きルートsignup_pathを使えるようにしてください。また、リスト 5.43で名前付きルートが使えるようになったので、現時点でテストが greenになっていることを確認してください。

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

演習5.4.2.2

<問題> 先ほどのテストが正しく動いていることを確認するため、signupルールの部分をコメントアウトし、テスト redになることを確認してください。確認できたら、コメントアウトを解除して greenの状態に戻してください。

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

演習5.4.2.3

<問題> リスト 5.32の統合テストにsignupページにアクセスするコードを追加してください (getメソッドを使います)。コードを追加したら実際にテストを実行し、結果が正しいことを確認してください。 ヒント: リスト 5.36で紹介したfull_titleヘルパーを使ってみてください。

<解答>

[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
    get contact_path
    assert_select "title", full_title("Contact")
    get signup_path
    assert_select "title", full_title("Sign up")
  end
end

関連記事

【第1章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第2章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第3章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第4章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第6章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第7章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第14章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

Rails 検索機能拡張 (rails tutorial) - 新米パパの育児留学

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。

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

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

演習問題と解答

演習4.2.2

演習4.2.2.1

<問題> city変数に適当な市区町村を、prefecture変数に適当な都道府県を代入してください。

<解答>

>>city="神戸"
=> "神戸"
>>prefecture="兵庫"
=> "兵庫"

演習4.2.2.2

<問題> 先ほど作った変数と式展開を使って、「東京都 新宿区」のような住所の文字列を作ってみましょう。出力にはputsを使ってください。

<解答>

>>puts "#{prefecture}県 #{city}市"
=> 兵庫県 神戸市

演習4.2.2.3

<問題> 上記の文字列の間にある半角スペースをタブに置き換えてみてください。(ヒント: 改行文字と同じで、タブも特殊文字です)

<解答>

>>puts "#{prefecture}県 \t #{city}市"
=> 兵庫県    神戸市

演習4.2.2.4

<問題> タブに置き換えた文字列を、ダブルクォートからシングルクォートに置き換えてみるとどうなるでしょうか?

<解答>

>>puts '#{prefecture}県 \t #{city}市'
=> #{prefecture}県 \t #{city}市

演習4.2.3

演習4.2.3.1

<問題> “racecar” の文字列の長さはいくつですか? lengthメソッドを使って調べてみてください。

<解答>

>> "racecar".length
=> 7

演習4.2.3.2

<問題> reverseメソッドを使って、"racecar"の文字列を逆から読むとどうなるか調べてみてください。

<解答>

>>"racecar".reverse
=> "racecar"

演習4.2.3.3

<問題> 変数sに “racecar” を代入してください。その後、比較演算子 (==) を使って変数sとs.reverseの値が同じであるかどうか、調べてみてください。

<解答>

>>s="racecar"
=> "racecar"
>>s==s.reverse
=> true

演習4.2.3.4

<問題> リスト 4.9を実行すると、どんな結果になるでしょうか? 変数sに “onomatopoeia” という文字列を代入するとどうなるでしょうか? ヒント: 上矢印 (またはCtrl-Pコマンド) を使って以前に使ったコマンドを再利用すると一からコマンドを全部打ち込む必要がなくて便利ですよ。)

<解答>

>>puts "It's a palindrome!" if s == s.reverse
=>It's a palindrome!

>>s="onomatopoeia"
=> "onomatopoeia"

>>puts "It's a palindrome!" if s == s.reverse
=> nil

演習4.2.4

演習4.2.4.1

<問題> リスト 4.10のFILL_INの部分を適切なコードに置き換え、回文かどうかをチェックするメソッドを定義してみてください。ヒント: リスト 4.9の比較方法を参考にしてください。

<解答>

>>def palindrome_tester(s)
>> if s==s.reverse
>>  puts "It's a palindrome!"
>> else
>>  puts "It's not a palindrome."
>> end
>>end
=> :palindrome_tester

演習4.2.4.2

<問題> 上で定義したメソッドを使って “racecar” と “onomatopoeia” が回文かどうかを確かめてみてください。1つ目は回文である、2つ目は回文でない、という結果になれば成功です。

<解答>

>>palindrome_tester("racecar")
=>It's a palindrome!
=> nil

>>palindrome_tester("onomatopoeia")
=>It's not a palindrome.
=> nil

演習4.2.4.3

<問題> palindrome_tester(“racecar”)に対してnil?メソッドを呼び出し、戻り値がnilであるかどうかを確認してみてください (つまりnil?を呼び出した結果がtrueであることを確認してください)。このメソッドチェーンは、nil?メソッドがリスト 4.10の戻り値を受け取り、その結果を返しているという意味になります。

<解答>

>>palindrome_tester("racecar").nil?
=>It's a palindrome!
=> true

演習4.3.1

演習4.3.1.1

<問題> 文字列 “A man, a plan, a canal, Panama” を “, ” で分割して配列にし、変数aに代入してみてください。

<解答>

>>a= "A man, a plan, a canal, Panama".split(', ')
=> ["A man", "a plan", "a canal", "Panama"]

演習4.3.1.2

<問題> 今度は、変数aの要素を連結した結果 (文字列) を、変数sに代入してみてください。

<解答>

>>s=a.join
=> "A mana plana canalPanama"

演習4.3.1.3

<問題> 変数sを半角スペースで分割した後、もう一度連結して文字列にしてください (ヒント: メソッドチェーンを使うと1行でもできます)。リスト 4.10で使った回文をチェックするメソッドを使って、(現状ではまだ) 変数sが回文ではないことを確認してください。downcaseメソッドを使って、s.downcaseは回文であることを確認してください。

<解答>

>>def palindrome_tester(s)
>> if s==s.reverse
>>  puts "It's a palindrome!"
>> else
>>  puts "It's not a palindrome."
>> end
>>end
=> :palindrome_tester

>>palindrome_tester(s)
=>It's not a palindrome.
=> nil

>>def palindrome_tester(s)
>> if s=s.reverse
>>  puts "It's a palindrome!"
>> else
>>  puts "It's not a palindrome."
>> end
>>end
=> :palindrome_tester

>>palindrome_tester(s.split.join.downcase)
=>It's a palindrome!
=> nil

演習4.3.1.4

<問題> aからzまでの範囲オブジェクトを作成し、7番目の要素を取り出してみてください。同様にして、後ろから7番目の要素を取り出してみてください。(ヒント: 範囲オブジェクトを配列に変換するのを忘れないでください)

<解答>

>>a=('a'..'z').to_a
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

>>a[7]
=> "h"

>>a[-7]
=> "t"

演習4.3.2

演習4.3.2.1

<問題> 範囲オブジェクト0..16を使って、各要素の2乗を出力してください。

<解答>

>>(0..16).each do |i|
>> puts i*i
>>end
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256
=> 0..16

演習4.3.2.2

<問題> yeller (大声で叫ぶ) というメソッドを定義してください。このメソッドは、文字列の要素で構成された配列を受け取り、各要素を連結した後、大文字にして結果を返します。例えばyeller([’o’, ’l’, ’d’])と実行したとき、"OLD"という結果が返ってくれば成功です。ヒント: mapとupcaseとjoinメソッドを使ってみましょう。

<解答>

>>def yeller(s)
>> s.join.upcase
>>end
=> :yeller

>>yeller(['o', 'l', 'd'])
=> "OLD"

演習4.3.2.3

<問題> random_subdomainというメソッドを定義してください。このメソッドはランダムな8文字を生成し、文字列として返します。ヒント: サブドメインを作るときに使ったRubyコードをメソッド化したものです。

<解答>

>>def random_subdomain(a)
>> a.to_a.shuffle[0..7].join
>>end
=> :random_subdomain

>>random_subdomain('a'..'z')
=> "vjqfctag"

a~zのみではなく、0~9も含めたランダム8文字生成方法

>>a="a".."z"
=> "a".."z"

>>b=0..9
=> 0..9

>>a.to_a.concat(b.to_a)
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]

>>def random_subdomain(a)
>> a.to_a.shuffle[0..7].join
>>end
=> :random_subdomain

>>random_subdomain(a.to_a.concat(b.to_a))
=> "cin362ps"

concatメソッドは、配列arrayの末尾に引数の配列other_arrayを結合します。

演習4.3.2.4

<問題> リスト 4.12の「?」の部分を、それぞれ適切なメソッドに置き換えてみてください。ヒント:split、shuffle、joinメソッドを組み合わせると、メソッドに渡された文字列 (引数) をシャッフルさせることができます

<解答>

>>def string_shuffle(s)
>> s.split('').shuffle.join
>>end
=> :string_shuffle

>>string_shuffle("foobar")
=> "arobof"

演習4.3.3

演習4.3.3.1

<問題> キーが’one’、’two’、’three’となっていて、それぞれの値が’uno’、’dos’、’tres’となっているハッシュを作ってみてください。その後、ハッシュの各要素をみて、それぞれのキーと値を"’#{key}’のスペイン語は’#{value}’"といった形で出力してみてください。

<解答>

>>flash={one:"uno",two:"dos",three:"tres"}
=> {:one=>"uno", :two=>"dos", :three=>"tres"}

>>flash.each do |key, value|
>> puts "'#{key}'のスペイン語は'#{value}'"
>>end
'one'のスペイン語は'uno'
'two'のスペイン語は'dos'
'three'のスペイン語は'tres'
=> {:one=>"uno", :two=>"dos", :three=>"tres"}

演習4.3.3.2

<問題> person1、person2、person3という3つのハッシュを作成し、それぞれのハッシュに:firstと:lastキーを追加し、適当な値 (名前など) を入力してください。その後、次のようなparamsというハッシュのハッシュを作ってみてください。1.) キーparams[:father]の値にperson1を代入、2). キーparams[:mother]の値にperson2を代入、3). キーparams[:child]の値にperson3を代入。最後に、ハッシュのハッシュを調べていき、正しい値になっているか確かめてみてください。(例えばparams[:father][:first]がperson1[:first]と一致しているか確かめてみてください)

<解答>

person1={first:"suzuki",last:"ichiro"}
=> {:first=>"suzuki", :last=>"ichiro"}

person2={first:"tanaka",last:"hanako"}
=> {:first=>"tanaka", :last=>"hanako"}

person3={first:"sato",last:"takashi"}
=> {:first=>"sato", :last=>"takashi"}

params={}
=> {}

params[:father]=person1
=> {:first=>"suzuki", :last=>"ichiro"}

params[:mother]=person2
=> {:first=>"tanaka", :last=>"hanako"}

params[:child]=person3
=> {:first=>"sato", :last=>"takashi"}

params
=> {:father=>{:first=>"suzuki", :last=>"ichiro"}, :mother=>{:first=>"tanaka", :last=>"hanako"}, :child=>{:first=>"sato", :last=>"takashi"}}

params[:father][:last]
=> "ichiro"

params[:child][:first]
=> "sato"

演習4.3.3.3

<問題> userというハッシュを定義してみてください。このハッシュは3つのキー:name、:email、:password_digestを持っていて、それぞれの値にあなたの名前、あなたのメールアドレス、そして16文字からなるランダムな文字列が代入されています。

<解答>

user={name:"yamada",email:"yamada@gmail.com",password_digest:"asdfghjk12345678"}
=> {:name=>"yamada", :email=>"yamada@gmail.com", :password_digest=>"asdfghjk12345678"}

演習4.3.3.4

<問題> Ruby API (訳注: もしくはるりまサーチ) を使って、Hashクラスのmergeメソッドについて調べてみてください。次のコードを実行せずに、どのような結果が返ってくるか推測できますか? 推測できたら、実際にコードを実行して推測があっていたか確認してみましょう。

<解答>

{ "a" => 100, "b" => 200 }.merge({ "b" => 300 })
=> {"a"=>100, "b"=>300}

重複するbは引数が適用される

演習4.4.1

演習4.4.1.1

<問題> 1から10の範囲オブジェクトを生成するリテラルコンストラクタは何でしたか? (復習です)

<解答>

a=1..10
=> 1..10

演習4.4.1.2

<問題> 今度はRangeクラスとnewメソッドを使って、1から10の範囲オブジェクトを作ってみてください。ヒント: newメソッドに2つの引数を渡す必要があります

<解答>

b=Range.new(1,10)
=> 1..10

演習4.4.1.3

<問題> 比較演算子==を使って、上記2つの課題で作ったそれぞれのオブジェクトが同じであることを確認してみてください。

<解答>

a==b
=> true

演習4.4.2

演習4.4.2.1

<問題> Rangeクラスの継承階層を調べてみてください。同様にして、HashとSymbolクラスの継承階層も調べてみてください。

<解答>

Range => Class=> Module=> Object=> BasicObject

Hash,Symbolも同じ

演習4.4.2.2

<問題> リスト 4.15にあるself.reverseのselfを省略し、reverseと書いてもうまく動くことを確認してみてください。

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

演習4.4.3

演習4.4.3.1

<問題> palindrome?メソッドを使って、“racecar”が回文であり、“onomatopoeia”が回文でないことを確認してみてください。南インドの言葉「Malayalam」は回文でしょうか? ヒント: downcaseメソッドで小文字にすることを忘れないで。

<解答>

>>class String
>> def palindrome?
>>  self==reverse
>> end
>>end
=> :palindrome?

>>"racecar".palindrome?
=> true

>>"onomatopoeia".palindrome?
=> false

>>"Malayalam".downcase.palindrome?
=> true

演習4.4.3.2

<問題> リスト 4.16を参考に、Stringクラスにshuffleメソッドを追加してみてください。 ヒント: リスト 4.12も参考になります。

<解答>

class String
def shuffle
self.split('').shuffle.join
end
end
=> :shuffle
"foobar".shuffle
=> "rfooba"

演習4.4.3.3

<問題> リスト 4.16のコードにおいて、self.を削除してもうまく動くことを確認してください。

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

演習4.4.4

演習4.4.4.1

<問題> 第2章で作ったToyアプリケーションのディレクトリでRailsコンソールを開き、User.newと実行することでuserオブジェクトが生成できることを確認してみましょう。

<解答>

>>User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

演習4.4.4.2

<問題> 生成したuserオブジェクトのクラスの継承階層を調べてみてください。

<解答>

User => Class=> Module=> Object=> BasicObject

演習4.4.5

演習4.4.5.1

<問題> Userクラスで定義されているname属性を修正して、first_name属性とlast_name属性に分割してみましょう。また、それらの属性を使って “Michael Hartl” といった文字列を返すfull_nameメソッドを定義してみてください。最後に、formatted_emailメソッドのnameの部分を、full_nameに置き換えてみましょう (元々の結果と同じになっていれば成功です)

<解答>

[example_user.rb]

class User
 attr_accessor :first_name,:last_name, :email

 def initialize(attributes = {})
  @first_name = attributes[:first_name]
  @last_name = attributes[:last_name]
  @email = attributes[:email]
 end

 def full_name
  @full_name = @first_name + @last_name
 end

 def formatted_email
  "#{@full_name} <#{@email}>"
 end
end

[console]

>>require './example_user'
=> true

>>user = User.new(first_name: "Michael", last_name: "Hartl", email: "mhartl@example.com")
=> #<User:0x00000002d21bd8 @first_name="Michael", @last_name="Hartl", 

>>@email="mhartl@example.com"
>>user.full_name
=> "MichaelHartl"

>>user.formatted_email
=> "MichaelHartl mhartl@example.com"

演習4.4.5.2

<問題> “Hartl, Michael” といったフォーマット (苗字と名前がカンマ+半角スペースで区切られている文字列) で返すalphabetical_nameメソッドを定義してみましょう。

<解答>

[example_user.rb]

class User
 attr_accessor :first_name,:last_name, :email

 def initialize(attributes = {})
  @first_name = attributes[:first_name]
  @last_name = attributes[:last_name]
  @email = attributes[:email]
 end

 def full_name
  @full_name = @first_name + @last_name
 end

 def alphabetical_name
  @alphabetical_name = "#{@first_name}, #{@last_name}"
 end

 def formatted_email_full
  "#{@full_name} <#{@email}>"
 end

 def formatted_email_al
  "#{@alphabetical_name} <#{@email}>"
 end
end

[console]

>>require './example_user'
=> true

>>user = User.new(first_name: "Michael", last_name: "Hartl", email: "mhartl@example.com")
=> #<User:0x00000003fd67b0 @first_name="Michael", @last_name="Hartl", 

>>@email="mhartl@example.com">
>>user.alphabetical_name
=> "Michael, Hartl"

>>user.formatted_email_al
=> "Michael, Hartl mhartl@example.com"

演習4.4.5.3

<問題> full_name.splitとalphabetical_name.split(’, ’).reverseの結果を比較し、同じ結果になるかどうか確認してみましょう。

<解答>

[console]

>>user.full_name.split
=> ["MichaelHartl"]

>>user.alphabetical_name.split(', ').reverse
=> ["Hartl", "Michael"]

>>user.formatted_email_full
=> "MichaelHartl mhartl@example.com"

>>user.formatted_email_al
=> "Michael, Hartl mhartl@example.com"

⇒同じになる

関連記事

【第1章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第2章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第3章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第5章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第6章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第7章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第14章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

Rails 検索機能拡張 (rails tutorial) - 新米パパの育児留学

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。

プログラミング学習ロードマップ(Ruby on Rails)

こんにちは!エンジニアを目指す育休中新米パパのmochikichiです。 
 
先日の記事でも触れましたが、現在、侍エンジニアOnlineというプログラミング学習オンラインコミュニティに参加しています。本日、その侍エンジニアOnlineのイベント「最適な学習ロードマップを作成しよう」に参加しました。
今回は作成した学習ロードマップを公開します! 
 

f:id:mochikichi321:20170211205114j:plain

ポイント

・目標からの逆算で考える(仕事獲得後の目標もありますが、今回は仕事獲得までのロードマップを記載)

・期限を明確化(〇月中ではなく、〇月△日までにXを完了する。)

・課題を明確化

・公言する(まさにこのブログ。勇気いるけど宣言すると実現性高まります。)

 

現状

まず、簡単にこれまでの学習経過と現状のご紹介です。(詳細は下記の過去記事を参照。)
2017年1月 Progateにて「Ruby」、「Ruby on Rails」を学習し始め、1月中に完了。
1/29、「Ruby on Rails Tutorial」の第4章を学習途中。【ブログ開始日】
 
2/11 現在、Ruby on Rails Tutorial」の第9章を学習中。
 

目標

4/12までにRuby案件の仕事獲得(以前は4月中でしたが明確化)
 

学習計画

スキル面
・「Ruby on Rails Tutorial」を完了(以下、更に細分化)【2/25まで】
 9章 2/13
 10章 2/15
 11章 2/17
 12章 2/19
 13章 2/22
 14章 2/25
 
Ruby on Rails Tutorial」に機能を3つ加えたポートフォリオを作成【3/11まで】
 機能選定:2/28
 実装:3/11
  
マーケティング
ポートフォリオ作成後、Wantedly,クラウドソーシングへ応募【3/12
・ブログに仕事受付ページをリンクさせる3/12
 

課題

ポートフォリオに実装する機能が現時点では決まっていない
 
「対策」
・既存のサービスで良い機能のものを実装する。
・自分が不便だと思うポイントを直す機能を実装する。
 

関連記事

これまでに学習してきたRuby on Rails Tutorial」の演習をまとめていっています。随時更新します。
 

mochikichi.hatenablog.com

mochikichi.hatenablog.com

mochikichi.hatenablog.com

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。

長時間残業問題 働き方改革の本質とは?

 

 

こんにちは!エンジニアを目指す育休中新米パパのmochikichiです。

 

はじめに

 

最近、長時間残業が問題視されており、「働き方改革」について様々な議論がされており、ニュースでもよく見かけます。しかし、どのニュースを見ても、「残業時間の上限を厳しくする」などの「小手先の対策」しかされておらず、問題はそこじゃないのになぁとモヤモヤとした気持ちで見ていました。

以下の記事は私もかなり共感できる本質的な内容を書かれていたので紹介と意見を書いていきます。

 

f:id:mochikichi321:20170210220159j:plain

 

引用記事の概要

組織の改革に必要なのは「団結」or「退出」

「団結」:組織に所属しているメンバーの大多数が一致団結して行うことによって効力を発揮

「退出」:優秀な人材がどんどん社外へと転職し、会社が危機感を感じ改革が起きる

 

世の中の企業は「ムーブ型企業」と「ステイ型企業」に分類

ムーブ型企業:社員の多くが簡単に転職などで他社に移る企業(いわゆるベンチャー系に多い)

ステイ型企業:社員が転職などで社外に流出することがほとんどない企業(いわゆる大手系に多い)

 

 ムーブ型企業:「団結」による改革力 < 「退出」による改革力

 ステイ型企業:「団結」による改革力 > 「退出」による改革力

 

近年の状況

 ・さまざまな背景・考え方を持った世代の人が入り混じり、「団結」の難易度が上昇

・「退出」の改革のメカニズムは、特定一部の課題にもすばやく発動しやすい

 

以下のような考えが支持される傾向

・「団結」が改革の主軸であるステイ型企業は時代とマッチしづらくなりつつあり

・「退出」を主軸としたムーブ型企業への移行を社会・制度全体としても推し進めていくべき

 

「団結」に必要な深堀したい3つのテーマ

 

テーマ1:仕事の生産性を高める余地はあるか

テーマ2:子育ての男女分担はどうあるべきか

テーマ3:仕事は「楽しむ」ものか「苦しい」ものか

 

mirai.doda.jp

 

自分の考え

 まず、自分が今いる会社は間違いなく「ステイ型組織」です。

その中で自分なりにいろいろチャレンジしています。

ただ、自分の意識と会社の大多数の人の意識にギャップを感じました。

深堀テーマを見ていきます。

 

テーマ1:仕事の生産性を高める余地はあるか

「自分」

早く帰宅して家族との時間や自分の自己啓発に時間を作りたいので、いかにして生産性を高めるかを考える。業務のやり方やITツールも新しいものを取り入れていきたいと思っている。

「会社」

上司は「長時間残業をしている=仕事を頑張っている」という見方。

社員は、生産性を高めるために脳をフル活用していろいろチャレンジしてやり方を変える努力をするよりも、今までのやり方で帰宅が遅くなるのを我慢する方がラク。

 

テーマ2:子育ての男女分担はどうあるべきか

「自分」

夫婦で子育てをしたい。現在、育休を取っているのもその一つ。詳細は以下参照。

mochikichi.hatenablog.com

男性の育休取得に対する相談も受け付けております。

「会社」

男は仕事をするものだ。家庭よりも業務を優先すべき。

育休取られると迷惑だ。

 

テーマ3:仕事は「楽しむ」ものか「苦しい」ものか

「自分」

当然、「楽しむ」もの。仕事をプライベートに活かすし、プライベートを仕事に活かす。そもそも線引きがないくらい楽しめるものが理想。

「会社」

当然、「苦しい」もの。もちろん楽しいこともあるがほとんどが大変で苦しいもの。

平日は会社で「頑張る」休日は好きなことをして「楽しむ」。ON、OFF切り分ける。

 

結論

理想は「団結」による改革ですが、現実は「退出」による改革でしょう。

ムーブ型企業が主流となると、個人の能力がかなり重要になってきます。

ステイ型企業でいろいろチャレンジしながら、ムーブ型企業が主流の社会にも対応していけるよう、個人の能力磨きをしていっています。詳細は以下参照。

 

みなさんの会社は「ムーブ型」、「ステイ型」どちらですか?

また、働き方改革についての意見も教えてください。

 

mochikichi.hatenablog.com

c-xiaxiang.hatenablog.com

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

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

演習問題と解答

演習3.1

演習3.1.1

<問題> BitbucketがMarkdown記法のREADME (リスト 3.3) をHTMLとして正しく描画しているか、確認してみてください。

<解答>

f:id:mochikichi321:20170209195943p:plain

演習3.1.2

<問題> 本番環境 (Heroku) のルートURLにアクセスして、デプロイが成功したかどうか確かめてみてください。

<解答>

動作確認なので省略

演習3.2.1

演習3.2.1.1

<問題> Fooというコントローラを生成し、その中にbarとbazアクションを追加してみてください。

<解答>

$ rails g controller Foo bar baz

上記のコマンドで以下が生成されます。

[foo_controller.rb]

class FooController < ApplicationController
  def bar
  end

  def baz
  end
end

[routes.rb]

Rails.application.routes.draw do
  get 'foo/bar'
  get 'foo/baz'
(中略)
end

演習3.2.1.2

<問題> コラム 3.1で紹介してテクニックを駆使して、Fooコントローラとそれに関連するアクションを削除してみてください。

<解答>

$ rails d controller Foo bar baz

演習3.4.2

演習3.4.2.1

<問題> StaticPagesコントローラのテスト (リスト 3.24) には、いくつか繰り返しがあったことにお気づきでしょうか? 特に「Ruby on Rails Tutorial Sample App」という基本タイトルは、各テストで毎回同じ内容を書いてしまっています。そこで、setupという特別なメソッド (各テストが実行される直前で実行されるメソッド) を使って、この問題を解決したいと思います。まずは、リスト3.30のテストが green になることを確認してみてください (リスト 3.30では、2.2.2で少し触れたインスタンス変数や文字列の式展開というテクニックを使っています。それぞれ4.4.5と4.2.2で詳しく解説するので、今はわからなくても問題ありません)。

<解答>

動作確認なので省略。

演習3.4.3

演習3.4.3.1

<問題> サンプルアプリケーションにContact (問い合わせ先) ページを作成してください16 (ヒント: まずはリスト 3.15を参考にして、/static_pages/contactというURLのページに「Contact | Ruby on Rails Tutorial Sample App」というタイトルが存在するかどうかを確認するテストを最初に作成しましょう。次に、3.3.3でAboutページを作ったときのと同じように、Contactページにもリスト 3.40のコンテンツを表示してみましょう。)。

<解答>

テスト記載。

[static_pages_controller_test.rb]

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest

(中略)

  test "should get contact" do
    get static_pages_contact_url
    assert_response :success
    assert_select "title", "Contact | Ruby on Rails Tutorial Sample App"
  end
end

ルーティング記載。

[routes.rb]

Rails.application.routes.draw do

(中略)

  get  'static_pages/contact'
end

コントローラーに"contact"アクション追加。

[static_pages_controller.rb]

class StaticPagesController < ApplicationController

(中略)

  def contact
  end
end

Contactページ編集。

[static_pages/contact.html.erb]

<% provide(:title, 'Contact') %>
<h1>Contact</h1>
<p>
  Contact the Ruby on Rails Tutorial about the sample app at the
  <a href="http://railstutorial.jp/contact">contact page</a>.
</p>

演習3.4.4

演習3.4.4.1

<問題> リスト 3.41にrootルーティングを追加したことで、root_urlというRailsヘルパーが使えるようになりました (以前、static_pages_home_urlが使えるようになったときと同じです)。リスト 3.42のFILL_INと記された部分を置き換えて、rootルーティングのテストを書いてみてください。

<解答>

[static_pages_controller_test.rb]

require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  
  def setup
    @base_title="Ruby on Rails Tutorial Sample App"
  end
  
  test "should get root" do
    get root_url
    assert_response :success
  end
(中略)
end

演習3.4.4.2

<問題> 実はリスト 3.41のコードを書いていたので、先ほどの課題のテストは既に green になっているはずです。このような場合、テストを変更する前から成功していたのか、変更した後に成功するようになったのか、判断が難しいです。リスト 3.41のコードがテスト結果に影響を与えていることを確認するため、リスト 3.43のようにrootルーティングをコメントアウトして見て、 red になるかどうか確かめてみましょう (なおRubyのコメント機能については4.2.1で説明します)。最後に、コメントアウトした箇所を元に戻し (すなわちリスト 3.41に戻し)、テストが green になることを確認してみましょう。

<解答>

動作確認なので省略。

関連記事

【第1章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第2章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第4章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第5章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第6章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第7章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第8章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第9章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第10章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第11章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第12章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第13章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

【第14章】Ruby on Rails チュートリアル 5.0(第4版)演習と解答まとめ - 新米パパの育児留学

Rails 検索機能拡張 (rails tutorial) - 新米パパの育児留学

プログラミング未経験から2か月でエンジニアへ転職したノウハウを知りたい方の相談も受け付けております。