rails beginner

→Railsビギナー 第0章はこちら

→Railsビギナー 第2章はこちら

→Railsビギナー 第3章はこちら

 

→Railsビギナー 免責事項 に同意いただける方のみ、教材の利用をお願いいたします。

 

まずはRailsアプリケーションを新規作成します。

Visual Studio Code(以下 VSCode)を開いてください。

railsビギナー

「control」+「shift」+「`」キーをクリックすると、ターミナル画面が開きます。

もしくは画面左上にある「ターミナル」をクリック →「新しいターミナル」をクリックでも開きます。

railsビギナー

 

ターミナルに「cd desktop」と入力して、desktopに移動してください。

railsビギナー

(↑「MacBook-Pro:~ (名前)」が「MacBook-Pro:desktop (名前)」に変更できました)

 

desktopに移動した状態で「rails new beginner_app」をターミナルに入力してください。

rails beginner

 

少し時間がかかります。

作成が終わると、desktopに「beginner_app」というアプリケーションが作成されます。

railsビギナー

 

作成された「beginner_app」をVSCodeで開いてください。

再びターミナルを開いて、下記のコマンドを入力してください。

(上記でターミナルの使い方の初歩は分かったと思うので、下記よりスクショではなくコマンドだけ載せています。)

rails server

※「rails s」と省略も可能

 

するとサーバが起動します。

ブラウザを開いて「localhost:3000」と入力すると、下記の画面が出ます。

railsビギナー

しっかり起動していると確認できましたね!

サーバの起動を終了させるには、サーバを起動させたターミナル上で、control + cをクリックしてください。

 

【注意!】

※今からコードをどんどん書いていきます。

エラーが解消できない、上手く動かないと思ったときは、まず以下のことを試してください。

・ブラウザをリロードする

・コードのタイプミスがないか確認する

・半角スペースが全角スペースになっていないか確認する

・サーバを再起動する

・SQLite3に関するエラーが出る場合は、一度サーバを終了させて、ターミナルを閉じ、再びターミナルを開き、rails sコマンドを入力してみる

コントローラーとモデルを作ろう!

女性 プログラマー

次は質問投稿機能に必要なコントローラーを作成します。

(コントローラーって何?と思った方は、プロゲートで復習しましょう。)

 

新しいターミナルを追加で開いてください。

VSCodeのターミナルの右端にあるプラスボタンをクリックすると、新しいターミナルが追加されます。

railsビギナー

追加で開いたターミナルに下記コマンドを入力しましょう。

rails generate controller questions

generateはgと省略することも可能です。

つまり「rails g controller questions」でもOK!

 

様々なファイルが作成されますが、今回はquestions_controller.rbファイルに注目。

questions_controller.rbファイルは、appフォルダの中の、controllersフォルダの中にあります。

railsビギナー

↑毎回、appフォルダの中の、controllersフォルダの中の…とか説明するのは冗長なので、次回以降はapp/controllers/questions_controller.rbと表記します。

 

このファイルにindexアクションを追加しましょう。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end
end

エディターに自動保存の設定している方は大丈夫ですが、設定していない方は「command」+「s」で保存しておきましょう。

※以降もコードを書いた後は「command」+「s」で保存してくださいね。

 

次はルーティングを記述するファイルに注目。

config/routes.rbファイルを開いて、3行目のコードを追加してください。

(下の方にあるconfig.ruファイルと間違いないように注意。)

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html  
  get "/questions", to: "questions#index"
end

このように記述することで、「localhost:3000/questions」というURLにアクセスがあったとき、questionsコントローラーのindexアクションを実行すると指定できます。

 

Railsではルーティング→コントローラー→ビューという流れで処理が行われます。

 

今の段階ではquestionsコントローラーのindexアクションに対応するビューがありません。

そのためindexアクションに対応するビューを作成します。

 

app/views/questionsフォルダの中に作ってください。

railsビギナー

questionsフォルダの上で右クリックして、新しいファイルをクリックして、index.html.erbというファイル名で作成します。

 

indexアクションに対応するビューのファイル名なので、index.html.erbにしてください。

違う名前をつけるとうまく動きません。

 

index.html.erbファイルに下記のコードを追加しましょう。

<%= @test %>

index.html.erbでは、questionsコントローラーのindexアクションで定義した@testを使うことができます。

 

とはいえindex.html.erbファイルは、あくまでhtmlファイルなのでRubyのコードをそのまま使うことはできません。

index.html.erbファイルでRubyのコードを取り扱うときは、<%= %>で囲んであげましょう。

× @test

○ <%= @test %>

 

ここまでで書いたコードの処理の流れをまとめると、「localhost:3000/questions」にアクセスがあると、questionsコントローラーのindexアクションが実行されて、index.html.erbファイルが返されるという感じです。

 

実際にブラウザを開いて「localhost:3000/questions」にアクセスしてみましょう。

railsビギナー

@testに入っている”テストテキスト”が表示されていますね。

 

アプリ作成者の文章を発信するだけなら、ルーティングを書いて、コントローラーとビューを作るだけで十分です。

けれども今回作るのは質問サイトです。

ユーザーが作成した質問を、データベースに保存する必要があります。

そのためデータベースとやり取りを行ってくれる、モデルの作成が必要です。

それではさっそくquestionモデルを作成します。

 

ターミナルに下記コマンドを入力しましょう。

rails g model question

今回は作成されたマイグレーションファイルに注目。

※マイグレーションファイルとは…データベースを作るときに使う設計図のようなもの

 

db/migrate/xxxxxxxxxxxxxx_create_questions.rbを開いてください。

(xxxxxxxxxxxxxxの部分には、作成した日付が入ります)

 

3行目にquestionsテーブルを作るという記述があります。

※テーブルとは…エクセルの表のようなものだと思ってください。テーブルにデータを格納していきます。

 

次はマイグレーションファイルに、下記のコードを追加します。

class CreateQuestions < ActiveRecord::Migration[6.0]
  def change
    create_table :questions do |t|
      t.string :title
      t.text :body
      t.timestamps
    end
  end
end

「string」と「text」はカラムの型を指定しています。

「string」と入力することで、このカラムには文字列を入力すると指定できます。

※カラムとは…テーブルの「列(縦軸)」のこと

 

「text」も同じく文字列の型ですが、「string」に比べて長文を入力できます。

※stringは255文字以下のみ入力可能

 

「:title」と「:body」で、カラムに名前をつけています。

つまり今回はquestionsテーブルに、string型のtitleというカラムと、text型のbodyというカラムを作ったことになります。

 

マイグレーションファイルを書き換えただけでは、データベースに反映されないので「rails db:migrate」をターミナルに入力します。

rails db:migrate

これでtitleカラムとbodyカラムを持ったquestionsテーブルを作成できました。

質問を新規作成できるようにしよう

rails beginner

せっかくテーブルを作ったので、質問の新規作成機能を作ります。

config/routes.rbに下記のコードを追加します。


Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get "/questions", to: "questions#index"
  get "/questions/new", to: "questions#new"
end

次はquestionsコントローラーにnewアクションを追加します。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def new
    @question = Question.new
  end
end

Question.newで空のインスタンスを作成しています。

「空のインスタンスを作成って何?」と思った方もいるはず。

そのためすこし、Question.newの処理について説明します。

 

ターミナルに下記のコマンドを入力してください。

rails c -s

railsコンソールが立ち上がります。

railsコンソールでどのような処理が行われているか見てみましょう。

※railsコンソールとは…Rubyのコードを動かすことができるツール

 

たとえば次のコマンド Question.new(title: “aaa”, body: “bbb”) を入力すると…

railsビギナー

(少し分かりにくいので、ここはスクショを使って説明)

(このコマンドはコピペすると上手く動かないようなので、コピペせずに入力してください)

 

以下のような表示があると思います。

railsビギナー

titleが”aaa”、bodyが”bbb”のインスタンスが作られました。

 

次は(title: “aaa”)のような値を渡さず、Question.newとだけ書いてみました。

すると空のインスタンスが作成されます。

railsビギナー

 

つまりquestionsコントローラーのnewアクションでは、空のインスタンスを作り、@questionという変数に代入しています。

なぜこのような変数を作ったのか?

答えはビューファイルを作成すれば分かります。

(railsコンソールは「exit」を入力すれば終了できます。終了しておきましょう。)

 

app/views/questions/new.html.erbを作成して、下記のコードを書いてください。

質問の新規投稿フォームを作成しています。

<%= form_with(model: @question, local: true) do |f| %>
  <div>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.text_area :body %>
  </div>
  <%= f.submit %>
<% end %>

何か見慣れないコードが出てきましたね。

railsはフォームを簡単に作れるように、form_withというヘルパーを用意しています。

※ヘルパーとは?…viewをシンプルに書けるように、処理をまとめたものです。

 

form_withのあとに、コントローラーのnewアクションで作った@questionを渡しています。

@questionには、Question.newで作成された空のインスタンスが入っていますね?

form_withは物凄く賢いので、「空のインスタンスってことは、新規作成したいのかな?」と判断してくれます。

(後ほど解説しますが、@questionに入っているのが空のインスタンスじゃない場合は、編集投稿フォームだと判断してくれます)

 

つまりQuestion.newで作成した空のインスタンスが入っている@questionを渡すことで、このフォームは質問の新規投稿フォームだと指定しています。

 

続いてそれ以外のコードも見ていきましょう。

<%= f.text_field :title %>は結果的に、下記のHTMLコードを生成します。

<input type="text" name="question[title]" id="question_title">

これでユーザーにタイトルを入力してもらうことができます。

 

<%= f.text_area :body%>は、下記のHTMLコードを生成します。

<textarea name="question[body]" id="question_body"></textarea>

text_fieldで作成されるフォームだと一行でしか入力できませんが、text_areaなら複数行で入力できるフォームを作れます。

 

次にフォームから送られてきた値を、データベースに保存できるようにしましょう。

config/routes.rbに下記のコードを追加してください。


Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get "/questions", to: "questions#index"
  get "/questions/new", to: "questions#new"
  post "/questions", to: "questions#create"
end

フォームで入力された値は、questionsコントローラーのcreateアクションで処理します。

それではquestionsコントローラーにcreateアクションを記述していきましょう。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def new
    @question = Question.new
  end

  def create
    @question = Question.new(question_params)
    if @question.save
      redirect_to("/questions/new")
    else
      render("questions/new")
    end
  end
  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

また訳の分からんコードがたくさん…

ひとつひとつ理解していきましょう!

 

まず20行目にあるコードに注目。

def question_params
  params.require(:question).permit(:title, :body)
end

Railsにはストロングパラメータという仕組みがあります。

セキュリティを強固にするために、指定されたパラメータのみ受け付ける仕組みです。

※パラメータとは…フォームなどから送られてきた値だと考えてください。

 

params.require(:question).permit(:title, :body)と記述することで、titleとbodyの値のみを受け付けることができます。

もし仮に、params.require(:question).permit(:title)と記述すると、bodyの値を受け取ることはできません。

 

フォームを改変されて、値を送信されると、こちらが意図しない値が送られることもあります。

そのためストロングパラメータで、こちらが指定した値のみ受け取るよう指定します。

 

次に、def question_paramsの上にあるprivateとは何か?

privateメソッド以下に書かれたコードは、このコントローラー内でしか使えません。

question_paramsは、このコントローラーでしか使わないのでprivate以下に記述しています。

あまり難しく考えず、ストロングパラメータを書くときは、そういうもんだと思ってください。

 

次は11行目に書かれているコードに注目してください。

@question = Question.new(question_params)

question_paramsで受け取る値を指定しましたね。

Question.new(question_params)でフォームから送られた値を使ってインスタンスを作り、@questionに代入します。

この時点ではまだデータベースに反映されていません。

@question.saveと書くことで、データベースに保存されます。

 

createアクションの目的は、データベースにデータを保存することです。

何かのビューファイルをユーザーに渡すことではありません。

そのため別にビューファイルは必要ありません。

 

とはいえこのままでは、次にどのような処理を行えばいいか分かりません。

そこで@question.saveが終わった後は、redirect_toを書き、どのURLに移動するか指定しましょう。

 

今回は質問の新規作成ページに戻らせます。

redirect_toのあとに、移動して欲しいURLを書けばいいだけです。

redirect_to("/questions/new")

こうすることで正常にデータベースに保存が行われた場合、新規作成のページに移動します。

 

しかしこれは正常にデータベースに保存が行われた場合の話です。

保存が失敗することもあります。

そのためif文で条件分岐させて、正常に保存できた場合の処理と、保存に失敗した場合の処理を書いています。

if @question.save
  redirect_to("/questions/new")
else
  render("questions/new")
end

とはいえ保存が失敗する場合って、どのような原因が考えられるのでしょうか?

一つの例としてバリデーションが考えられます。

バリデーションとは…保存されるデータを、本当に保存していいか検証すること

 

実際にバリデーションを書いてみましょう。

app/models/question.rbを開いて、下記のコードを追加してください。

class Question < ApplicationRecord
  validates :title, presence: true, length: { maximum: 100 }
  validates :body, length: { maximum: 3000 }
end

presence: trueと記述することで、titleを必須入力項目にできます。

そのためtitleに何も入力せずフォームの保存ボタンを押すと、保存が失敗します。

length:は文字数を制限する記述で、length: { maximum: 100 }と書くことで、101文字以上書くと、保存に失敗します。

 

このような保存に失敗した場合の処理を、else以下に記述しています。

render("questions/new")

render “questions/new”と書くことで、views/questions/new.html.erbファイルを、画面に表示することができます。

 

一度、保存に失敗した場合どうなるか見たいのですが…

このままでは「保存に失敗しました!」などのメッセージが出ないので、とても分かりにくいです。

そこでflashを使って、とりあえず簡易的にメッセージを表示させます。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def new
    @question = Question.new
  end

  def create
    @question = Question.new(question_params)
    if @question.save
       flash[:notice] = "成功!"
       redirect_to("/questions/new")
    else
       flash.now[:alert] = "失敗!"
       render("questions/new")
    end
  end

  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

redirect_toのときはflashを使い、renderのときはflash.nowを使います。

次にapp/views/layouts/application.html.erbの<body>タグの下に、コードを追加します。

<!DOCTYPE html>
<html>
  <head>
    <title>BeginnerApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <p><%= notice %></p>
    <p><%= alert %></p>
    <%= yield %>
  </body>
</html>

これだけで簡易的にですが、メッセージを表示することができます。

ブラウザを開いて「localhost:3000/questions/new」にアクセスして、titleのところを何も入力せず、bodyにだけ値を書いて、送信ボタンをクリックしてください。

(一度、ブラウザの更新ボタンを押してからにしてくださいね)

railsビギナー

ちゃんと「失敗!」と表示されましたね。

 

ここでredirect_toとrenderの違いって何?と思った方。

しっかり考えながら読んでいる証拠です。

めちゃくちゃ勉強が上手いです。

最高です。

いや、マジで。

 

まずredirect_toの後に記述するのは、URLです。

renderの後に記述するのは、ビューのファイル名です。

redirect_toだと、新しいリクエストが発行されます。

つまりルーティング→コントローラー→ビューといういつもの流れで、ユーザーにページを返します。

 

renderはビューのファイルを呼ぶだけで、ルーティングにいって、コントローラーにいって…という処理がありません。

 

いまいちピンッとこないと思うので、実際にredirect_toが行われた場合の処理と、renderが行われた場合の処理を、見比べてみましょう。

 

app/controllers/questions_controller.rbの、newアクションとcreateアクションにコードを追加してください。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def new
    @question = Question.new
    @test = "new_テストテキスト"
  end

  def create
    @question = Question.new(question_params)
    @test = "create_テストテキスト"
    if @question.save
      flash[:notice] = "成功!"
      redirect_to("/questions/new")
    else
      flash.now[:alert] = "失敗!"
      render("questions/new")
    end
  end

  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

この@testは処理の違いを見るための、ちょっとした目印として使います。

次はapp/views/questions/new.html.erbに、コードを追加してください。

<%= form_with(model: @question, local: true) do |f| %>
  <div>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.text_area :body %>
  </div>
  <%= f.submit %>
<% end %>
<div>
  <%= @test %>
</div>

ブラウザを開いて、「localhost:3000/questions/new」にアクセスしてください。

<%= @test %>の部分は展開されて、”new_テストテキスト”と表示されていますね。

 

まずは保存に成功するケースを見てみましょう。

titleとbodyに何か適当な値を入力してください。

railsビギナー

送信ボタンをクリックすると、保存に成功します。

railsビギナー

このときの処理は下記のようになります。

redirect_toの流れ

questionsコントローラーのcreateアクションが実行される

保存に成功!

redirect_to(“/questions/new”)を実行して、URL「/questions/new」にアクセスする

URL「/questions/new」にアクセスがあると、questionsコントローラーのnewアクションが実行される

newアクションがapp/views/questions/new.html.erbをユーザーに返す

 

今までの知識を活かせば、特に問題なく理解できると思います。

 

次は保存に失敗するケースを見てみましょう。

titleには何も入力せず、bodyには何か適当な値を入力してください。

送信ボタンをクリックすると、保存に失敗します。

このときの処理は下記のようになります。

renderの流れ

questionsコントローラーのcreateアクションが実行される

保存に失敗!

render(“questions/new”)を実行して、app/views/questions/new.html.erbをユーザーに返す

 

そして注目してほしいのが、<%= @test %>の部分です。

railsビギナー

保存に成功した(redirect_toされた)ときは、”new_テストテキスト”と表示されていましたが、保存に失敗した(renderされた)ときは、”create_テストテキスト”と表示されていますね?

 

redirect_toだと新しいリクエストが発行されて、newアクションで定義した@testが使われています。

しかしrenderは新しいリクエストを発行していません。

createアクションにいる状態で、無理やりapp/views/questions/new.html.erbを呼び出しています。

createアクションにいるので、newアクションで定義している@testは使えません。

そのためrenderで呼び出したapp/views/questions/new.html.erbには、createアクションで定義した@testを渡しています。

 

何となく理屈は分かったかもしれませんが、なぜ保存に失敗した場合はrenderを使うのか?

 

もし仮に保存に失敗した場合もredirect_toを使うと、今まで入力した値が真っさらになります。

(newアクションで定義されている、空のインスタンスが入った@questionを使うため)

 

しかしrenderを使うと、保存に失敗した場合、入力した値を保持してページを返すことができます。

(createアクションで定義されている、フォームから送信された値が入った@questionを使うため)

試しにtitleに何も入れず、bodyに「ddd」と入力して、送信ボタンをクリックします。

 

失敗しても「ddd」が残ったままになっています。

railsビギナー

保存に失敗した時、もし長文を入力していた場合、また一から入力するのは手間ですよね。

そのためユーザーの利便性を考えた結果、保存に失敗した場合の処理はrenderを使っています。

質問を表示できる機能を作ろう

rails beginner

作成した質問を表示する機能を作ります。

まずはconfig/routes.rbに下記のコードを追加しましょう。

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get "/questions", to: "questions#index"
  get "/questions/new", to: "questions#new"
  post "/questions", to: "questions#create"
  get "/questions/:id", to: "questions#show"
end

次にデータベースから、データを取得する方法について見てみます。

railsコンソールで確認してみましょう。

rails c -s
Question.find(1)

Question.find(1)と入力することで、Questionsテーブルに入っている、idが1のレコードを取得できます。

railsビギナー

※レコードとは…テーブルの「行(横軸)」のこと

 

idは重複することがありません。

そのため次に作られた質問のidは2になります。

つまりfindメソッドを使ってidを指定すれば、見たいレコードを取得できます。

(「exit」を入力してrailsコンソールを終了しておきましょう。)

 

次はquestionsコントローラーにshowアクションを作りましょう。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def show
    @question = Question.find(1)
  end

  def new
    @question = Question.new
    @test = "new_テストテキスト"
  end

  def create
    @question = Question.new(question_params)
    @test = "create_テストテキスト"
    if @question.save
      flash[:notice] = "成功!"
      redirect_to("/questions/new")
    else
      flash.now[:alert] = "失敗!"
      render("questions/new")
    end
  end

  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

うーん…

これではidが1の質問しか取得できません。

 

どうするか?

ユーザーに表示させたい質問のidを指定してもらって、そのidの質問を返せるようにします。

 

たとえばユーザーがid 1のレコードを見たいと思ったとき、URLはlocalhost:3000/questions/1と指定してもらいます。

つまり今回定義したURL ‘/questions/:id’の:id部分には、表示させたい質問のidを入れると考えてください。

このlocalhost:3000/questions/1の、「1」をコントローラーで取得します。

 

どうやって取得するのか?

下記のようにコードを書いてください。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def show
    @question = Question.find(params[:id])
  end

  def new
    @question = Question.new
    @test = "new_テストテキスト"
  end

  def create
    @question = Question.new(question_params)
    @test = "create_テストテキスト"
    if @question.save
      flash[:notice] = "成功!"
      redirect_to("/questions/new")
    else
      flash.now[:alert] = "失敗!"
      render("questions/new")
    end
  end

  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

ルーティングを定義するとき、get ‘/questions/:id’と記述しましたよね?

このように書くと、localhost:3000/questions/1の1には、:idというキーが紐づいています。

 

こんな感じ。

{“id” => “1”}

 

そして{“id” => “1”}から”1″を取り出すには、paramsを使います。

params[:id]と書くと、1が取り出されます。

※ここらへんの処理がピンッとこない方は、プロゲートでRubyを復習するといいかもしれません。

 

idが2の質問を見たいと思って、localhost:3000/questions/2にアクセスした場合はどうなるか?

 

{“id” => “2”}となっているので、paramsを使って”2″を取り出します。

つまり@question = Question.find(params[:id])というコードは、最終的に@question = Question.find(2)という意味を持ったコードになります。

※今回はまだ質問を1つしか作っていないので、viewファイルを作った後に、localhost:3000/questions/2にアクセスしてもエラーが表示されるだけです。

 

それではルーティングとコントローラーを書いたので、次はビューファイルを作成しましょう。

app/views/questionsフォルダに、show.html.erbというファイルを作成してください。

<p><%= @question.title %></p>
<p><%= @question.body %></p>

それではブラウザを開いて、「http://localhost:3000/questions/1」にアクセスしてみましょう。

作成した質問のtitleとbodyが表示されています。

railsビギナー

作成した質問を表示できるようになりました!

デザインを整えたり、コードを整えたりしよう

rails beginner

デザインを少し整えていきます。

app/views/layouts/application.html.erbにある、<%= yield %>をdivで囲って、class=”container”をつけましょう。

<!DOCTYPE html>
<html>
  <head>
    <title>BeginnerApp</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <p><%= notice %></p>
    <p><%= alert %></p>
    <div class="container">
      <%= yield %>
    </div>
  </body>
</html>

次はcssを書きます。

app/assets/stylesheets/application.cssを開いてください。

コメントがたくさんあるので、その下にコードを書いてください。

/* コメントがたくさん */

.container {
  width: 80%;
  margin: 20px auto;
}

input, textarea {
  box-sizing: border-box;
  width: 400px;
  padding: 6px;
}

input[type="submit"] {
  background-color: #FF5D57;
  border-radius: 5px;
  color: white;
  padding: 10px;
  text-align: center;
  width: 150px;
}

textarea {
  height: 120px;
}

HTMLやCSSに関してどのような処理をしているか分からない方は、プロゲートで復習してくださいね。

 

次はフォームにラベルをつけてあげましょう。

<%= form_with(model: @question, local: true) do |f| %>
  <div>
    <%= f.label :title, "タイトル" %><br>
    <%= f.text_field :title %>
  </div>
  <div>
    <%= f.label :body, "本文" %><br>
    <%= f.text_area :body %>
  </div>
  <%= f.submit %>
<% end %>
<div>
  <%= @test %>
</div>

12~14行目に書いているコードは、もう要らないので削除しておきましょう。

質問の新規投稿フォームは、このようになりました。

railsビギナー

app/controllers/questions_controller.rbの12行目と17行目書いている、@test = “new_テストテキスト”と@test = “create_テストテキスト”も削除してください。

あとcreateアクションのredirect_toのURLを変更します。

今までは新規作成フォームのページにとばしていましたが、せっかく作成したなら、作成した質問の詳細ページにとびたいですよね。

そこで redirect_to(“/questions/#{@question.id}”) というコードに書き換えます。

#{@question.id}の中には、作成した質問のidが入ります。

class QuestionsController < ApplicationController
  def index
    @test = "テストテキスト"
  end

  def show
    @question = Question.find(params[:id])
  end

  def new
    @question = Question.new
  end

  def create
    @question = Question.new(question_params)
    if @question.save
      flash[:notice] = "成功!"
      redirect_to("/questions/#{@question.id}")
    else
      flash.now[:alert] = "失敗!"
      render("questions/new")
    end
  end

  private
    def question_params
      params.require(:question).permit(:title, :body)
    end
end

最後に「localhost:3000」にアクセスしたとき、今までは初期画面を表示させていましたが、これからはapp/views/questions/index.html.erbを表示させます。

config/routes.rbに下記のコードを追加してください。

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  root to: 'questions#index'
  get "/questions", to: "questions#index"
  get "/questions/new", to: "questions#new"
  post "/questions", to: "questions#create"
  get "/questions/:id", to: "questions#show"
end

実際にブラウザを開いて「localhost:3000」にアクセスしてください。

app/views/questions/index.html.erbが表示されていますね。

railsビギナー

Railsビギナー 第1章「質問投稿機能を作ろう」まとめ

rails beginner

お疲れ様でした!

第1章終了です。

 

休憩がてらに、ぜひ下記の記事でも見てください。

ドン底から這い上がる過程を見れたり、フリーランスのリアルが分かったりするのでおすすめですよ↓

 

第2章ではユーザーのログイン・新規登録機能を、deviseというgemを使って作成します。

せっかく始めたのなら、ぜひ最後の第3章まで完走してくださいね!

←Railsビギナー 第0章はこちら

Railsビギナー 第2章はこちら→