おぴよの気まぐれ日記

おぴよの気まぐれ日記

岡山やプログラミング、ファッションのこと、子育てや人生、生き方についての備忘録。

30歳まで残り2年の僕は人生を変えるためにRailsブートキャンプを始めようと思う(第2章)

こんちには、opiyoです。

人生の生き残りをかけて始めた「Railsブートキャンプ」ですが、今日はRailsチュートリアル第2章をやっていこうと思います。

第1章をまとめたのはこちらからどうぞ。

opiyotan.hatenablog.com

モデル(Model)の作り方

  • ユーザーモデル

    • テーブル:users

    • カラム:id:integer, name:string, email:string

  • マイクロポストモデル

user_idを使って、1人のユーザーに対して複数のマイクロポストが関連付けるという構図になる。

テーブル名は複数形になるので注意!

scaffold

作成、一覧、編集、削除ができる機能を簡単に作ってくれる

$ rails g scaffold User name:string email:string # テーブル名は単数系だからね!
Expected string default value for '--jbuilder'; got true (boolean)
      invoke  active_record
      create    db/migrate/20170614093157_create_users.rb
      create    app/models/user.rb
      invoke    test_unit
      create      test/models/user_test.rb
      create      test/fixtures/users.yml
      invoke  resource_route
       route    resources :users
      invoke  scaffold_controller
      create    app/controllers/users_controller.rb
      invoke    erb
      create      app/views/users
      create      app/views/users/index.html.erb
      create      app/views/users/edit.html.erb
      create      app/views/users/show.html.erb
      create      app/views/users/new.html.erb
      create      app/views/users/_form.html.erb
      invoke    test_unit
      create      test/controllers/users_controller_test.rb
      invoke    helper
      create      app/helpers/users_helper.rb
      invoke      test_unit
      invoke    jbuilder
      create      app/views/users/index.json.jbuilder
      create      app/views/users/show.json.jbuilder
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/users.coffee
      invoke    scss
      create      app/assets/stylesheets/users.scss
      invoke  scss
      create    app/assets/stylesheets/scaffolds.scss

migrate

データベースを更新し、usersデータモデルを作成します。 db/migrateディレクトリにあるファイルを見て何をするか判断している。

$ rails db:migrate
== 20170614093157 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0019s
== 20170614093157 CreateUsers: migrated (0.0022s) =============================

nameemailを持った、usersテーブルを作るってことが分かりますね。

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.2.1 演習

<問題1> CSSを知っている読者へ: 新しいユーザーを作成し、ブラウザのHTMLインスペクター機能を使って「User was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

<回答1>場所は、bodyタグ直下にあってこんな感じ

  • <p id="notice">User was successfully created.</p>

リロードすると、pタグは残るが中身のメッセージが非表示になる

  • <p id="notice"></p>

<問題2> emailを入力せず、名前だけを入力しようとした場合、どうなるでしょうか?

<回答2> 名前のみ登録される

<問題3> 「@example.com」のような間違ったメールアドレスを入力して更新しようとした場合、どうなるでしょうか?

<回答3> 問題なく登録される

<問題4> 上記の演習で作成したユーザーを削除してみてください。ユーザーを削除したとき、Railsはどんなメッセージを表示するでしょうか?

<回答4> User was successfully destroyed.を表示する。

MVC(Model-View-Controller)の動き

「/users にあるindexページをブラウザで開く」という操作を行った時、どのように内部では処理が動くのか。

これは、Railsチュートリアルの方を見てください。図もあり説明もありなので分かりやすいです。

https://railstutorial.jp/chapters/toy_app?version=5.0#sec-mvc_in_action

2.2.2 演習

<問題1> 図 2.11を参考にしながら、/users/1/edit というURLにアクセスしたときの振る舞いについて図を書いてみてください。

<回答1> routes → コントローラーのeditアクション → モデル問い合わせなし → edit.html生成 → コントローラーがhtml受け取り → ブラウザへ返す

<問題2> 図示した振る舞いを見ながら、Scaffoldで生成されたコードの中でデータベースからユーザー情報を取得しているコードを探してみてください。

<回答2> @users = User.all

<問題3> ユーザーの情報を編集するページのファイル名は何でしょうか?

<回答3>edit.html.erb

2.3.1 演習

<問題1> CSSを知っている読者へ: 新しいマイクロポストを作成し、ブラウザのHTMLインスペクター機能を使って「Micropost was successfully created.」の箇所を調べてみてください。ブラウザをリロードすると、その箇所はどうなるでしょうか?

<回答1> 2.2.1 演習とほとんど同じ。

<問題2> マイクロポストの作成画面で、ContentもUserも空にして作成しようとするどうなるでしょうか?

<回答2> 問題なく登録できる。

<問題3> 141文字以上の文字列をContentに入力した状態で、マイクロポストを作成しようとするとどうなるでしょうか? (ヒント: WikipediaのRubyの記事にある1段落目がちょうど150文字程度ですが、どうなりますか?)

<回答3> 問題なく登録できる

<問題4> 上記の演習で作成したマイクロポストを削除してみましょう。

<回答4> 問題なく削除できる。

入力チェック(バリデーション)

モデルのファイルmicropost.rbで最大140文字までの入力チェックを付ける

class Micropost < ApplicationRecord
  validates :content, length: { maximum: 140 }
end

必須入力を付ける場合はpresence: trueを付ける

class Micropost < ApplicationRecord
  validates :content, length: { maximum: 140 }, presence: true
end

2.3.2演習

<問題1> 先ほど2.3.1.1の演習でやったように、もう一度Contentに141文字以上を入力してみましょう。どのように振る舞いが変わったでしょうか?

<回答1> Content is too long (maximum is 140 characters)というエラーメッセージが表示される

<問題2> CSSを知っている読者へ: ブラウザのHTMLインスペクター機能を使って、表示されたエラーメッセージを調べてみてください。

<回答2>

画面上部にエラーメッセージが表示される

<div id="error_explanation">
      <h2>1 error prohibited this micropost from being saved:</h2>

      <ul>
        <li>Content is too long (maximum is 140 characters)</li>
      </ul>
    </div>

Contentの入力欄が赤枠になる

<div class="field">
  <div class="field_with_errors"><label for="micropost_content">Content</label></div>
  <div class="field_with_errors"><textarea name="micropost[content]" id="micropost_content">12345678901234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
1234567890
  </textarea></div>
</div>

1対nの関連付け

これはRailsチュートリアルを参照してください。

https://railstutorial.jp/chapters/toy_app?version=5.0#sec-demo_user_has_many_microposts

簡単に書くと

  • 1の方にhas_manyを書いて、nを複数形で指定する
  • nの方にbelongs_toを書いて、1を単数系で指定する

Railsコンソール

データベースへアクセスし色々できる

$ rails c
exit # 終了

2.3.3 演習

<問題1> ユーザーのshowページを編集し、ユーザーの最初のマイクロポストを表示してみましょう。同ファイル内の他のコードから文法を推測してみてください (コラム 1.1で紹介した技術の出番です)。うまく表示できたかどうか、/users/1 にアクセスして確認してみましょう。

<回答1> users/show.html.erbに追加

<p>
  <strong>Content:</strong>
  <%= @user.microposts.first.content %>
</p>

<問題2>リスト 2.16は、マイクロポストのContentが存在しているかどうかを検証するバリデーションです。マイクロポストが空でないことを検証できているかどうか、実際に試してみましょう (図 2.16のようになっていると成功です)。

<回答2> app/models/micropost.rbを修正

class Micropost < ApplicationRecord
  belongs_to :user
  validates :content, length: { maximum: 140 }, presence: true
end

<問題3> リスト 2.17のFILL_INとなっている箇所を書き換えて、Userモデルのnameとemailが存在していることを検証してみてください (図 2.17)。

<回答3> app/models/user.rbを修正

class User < ApplicationRecord
  has_many :microposts
  validates :name, presence: true
  validates :email, presence: true
end

継承について

Railsチュートリアルを参照

https://railstutorial.jp/chapters/toy_app?version=5.0#sec-inheritance_hierarchies

  • モデルクラスの場合は、ApplicationRecordActiveRecord::Baseを継承している
  • データベースに接続する処理やデータベースを扱える処理はActiveRecord::Base側で定義されている
  • これによって、新しく作ったクラスでデータベースに接続する処理やデータベースを扱える処理を書かなくて色々できる
  • モデルだけじゃなくコントローラーも同じようになっている
  • コントローラーの場合はApplicationControllerを継承している

2.3.4 演習

<問題1>Applicationコントローラのファイルを開き、ApplicationControllerがActionController::Baseを継承している部分のコードを探してみてください。

<回答1> class ApplicationController < ActionController::Base

<問題2>ApplicationRecordがActiveRecord::Baseを継承しているコードはどこにあるでしょうか? 先ほどの演習を参考に、探してみてください。ヒント: コントローラと本質的には同じ仕組みなので、app/modelsディレクトリ内にあるファイルを調べてみると…?)

<回答2> app/models/application_record.rbclass ApplicationRecord < ActiveRecord::Base

herokuへのデプロイ

手順は1章と同じですが、今回はDBを新たに作ったのでマイグレーションをする必要があります

$ git add .
$ git commit -m "終わりー"
$ git push origin master
$ git push heroku
$ heroku run rails db:migrate
$ heroku open

その他メモ

  • 間違えてscaffoldしちゃっ時は削除できる
$ rails destroy scaffold Micropost
Running via Spring preloader in process 4158
Expected string default value for '--jbuilder'; got true (boolean)
      invoke  active_record
      remove    db/migrate/20170614102406_create_microposts.rb
      remove    app/models/micropost.rb
      invoke    test_unit
      remove      test/models/micropost_test.rb
      remove      test/fixtures/microposts.yml
      invoke  resource_route
       route    resources :microposts
      invoke  scaffold_controller
      remove    app/controllers/microposts_controller.rb
      invoke    erb
      remove      app/views/microposts
      remove      app/views/microposts/index.html.erb
      remove      app/views/microposts/edit.html.erb
      remove      app/views/microposts/show.html.erb
      remove      app/views/microposts/new.html.erb
      remove      app/views/microposts/_form.html.erb
      invoke    test_unit
      remove      test/controllers/microposts_controller_test.rb
      invoke    helper
      remove      app/helpers/microposts_helper.rb
      invoke      test_unit
      invoke    jbuilder
      remove      app/views/microposts
      remove      app/views/microposts/index.json.jbuilder
      remove      app/views/microposts/show.json.jbuilder
      invoke  assets
      invoke    coffee
      remove      app/assets/javascripts/microposts.coffee
      invoke    scss
      remove      app/assets/stylesheets/microposts.scss
      invoke  scss
  • 新しく綺麗な状態のDBを作りたいとき DB削除 → DB作成 → migrationを一発でやってくれる
$ rails db:migrate:reset
Dropped database 'db/development.sqlite3'
Database 'db/test.sqlite3' does not exist
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
== 20170614093157 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0021s
== 20170614093157 CreateUsers: migrated (0.0023s) =============================

== 20170614102713 CreateMicroposts: migrating =================================
-- create_table(:microposts)
   -> 0.0008s
== 20170614102713 CreateMicroposts: migrated (0.0009s) ========================