railsのまとめ6(ミニQ&Aサイトを作るその4)

5から続きます。

31:Postを押した時の保存処理の開発

rails routes #保存する際に必要な情報を見る
POST /questions/:question_id/answers(.:format) answers#create

app/controllers/answers_controller.rb

×だめな例
class AnswersController < ApplicationController

  def create
    @question = Question.find(params[:question_id])
    @answer = Answer.new
     if @answer.save
       redirect_to root_path, notice: 'Success!'
     else
       flash[:alert] = 'Save error!'
     render :show
   end
  end

   def edit
   end
end

viewに値を渡す必要がある変数の場合は、@を付ける。
逆に、viewに値を渡す必要がある変数の場合は@を付けない(付けても動作する)。
状況に応じて、使い分けをしているため、
やりたい処理によって付けたり付けなかったりする。
◯良い例

class AnswersController < ApplicationController

def create
  @question = Question.find(params[:question_id])
  @answer = Answer.new
    if @answer.update(answer_params)
      redirect_to question_path(@question), notice: 'Success!'
    else
      redirect_to question_path(@question), notice: 'Invalid!'
  end
end

  def edit
  end

private
  def answer_params
    params.require(:answer).permit(:content, :name, :question_id)
  end
end

ストロングパラメーター↑を作成しています。

32:Answerモデルのバリデーション

フォームに空で保存するのを禁止します。
app/models/answer.rbに記述↓

class Answer < ApplicationRecord
  belongs_to :question
    validates :content, presence: true
    validates :name, presence: true
end

33:回答一覧表示

app/views/answers/show.html.erbで記述を追加します。
<hr>

<div>
<h3>Answers</h3>
  <table class="table table-striped">
    <% if @question.answers.any? %>
      <thead class="thead-light">
        <tr>
          <td>Answer</td>
          <td>Name</td>
           <td>Menu</td>
        </tr>
      </thead>
   <tbody>
     <% @question.answers.each do |answer| %>
      <tr>
       <td><%= answer.content %></td>
       <td><%= answer.name %></td>
       <td>[edit] [Delete]</td>
      </tr>
    <% end %>
   </tbody>
  <% else %>
   <p>No answer yet.</p>
 <% end %>
</table>
</div>
@question = Question.find
#Quesutionsテーブルからfindしかしていないが

class Question < ApplicationRecord
  has_many :answers

回答一覧が表示されたらOKです。


これによって一つの質問に多くの回答が紐付いていて
Questionモデルをfindすることによって自動的に紐づく
answersのデータも取得することができる。
そして<% @question.answers.each do |answer| %>の部分で
@questionに紐づくanswersのデータを使うことができる
answersには配列でデータが入っているから|answer|

SQLは次のようになっている↓発行されたSQLは適宜確認しましょう!

SELECT "questions".* FROM "questions" WHERE "questions"."id" = ? LIMIT ? [["id", 10], ["LIMIT", 1]]
↳ app/controllers/questions_controller.rb:7
Rendering questions/show.html.erb within layouts/application
Answer Exists (0.1ms) SELECT 1 AS one FROM "answers" WHERE "answers"."question_id" = ? LIMIT ?

34:回答の編集

回答のeditを作ります。rails routesでルーティングの確認します。

edit_question_answer GET /questions/:question_id/answers/:id/edit(.:format) answers#edit

まずリンクを作リます。
app/views/answers/show.html.erbにて↓のように記述します。

<%= link_to ‘edit’, edit_question_answer_path(answer) %>

app/controllers/answers_controller.rbにて記述

def edit
  @question = Question.find(params[:question_id])
  @answer = @question.answers.find(params[:id])
end

@questionの該当のanswers_idを取得して@answerに代入
インスタンス変数なのでviewにわたすことができる

次にviewの編集をする
app/views/questions/show.html.erbにて↓のように記述します
第一引数に@question第2引数にanswerにします。
<%= link_to ‘edit’, edit_question_answer_path(@question, answer) %>

app/views/answers/edit.html.erbにて↓のように記述します。

<div>
<h2>Update answer</h2>
  <%= form_with model:[@question, @answer], local: true do |f| %>
    <div class="form-group">
    <div class="form-group">
  <label>Name</label>
<!--テキストフィールドをつける-->
   <%= f.text_field :name, class: "form-control" %>
    </div>
<!--テキストフィールドをつける-->
  <div class="form-group">
    <label>Content</label>
      <%= f.text_field :content, class: "form-control" %>
  </div>
<!--saveボタンを付ける-->
  <div class="text-center">
    <%= f.submit "Update", class: "btn btn-primary" %>
  </div>
 </div>
<% end %>
</div>

更新画面が表示されたらOKです。

続きルーティングの確認↓

PATCH /questions/:id(.:format) questions#update
PUT /questions/:id(.:format) questions#update

PUTやPATCH:リソースの作成または置換の時に使われるhtmlメソッドPOSTと似ているが厳密には違うものです。

app/controllers/answers_controller.rbにてprivateの上に記述します。

def update
  @question = Question.find(params[:question_id])
  @answer = @question.answers.find(params[:id])
    if @answer.update(answer_params)
      redirect_to question_path(@question), notice: 'Success!'
    else
     flash[:alert] = 'Invalid!'
     render :edit
 end
end

redirect_to question_path(@question)←の部分はidの部分なので忘れないように

 

35:回答の削除の実装

まずルーティングの確認をします。

rails routes

question_answer GET
/questions/:question_id/answers/:id(.:format) answers#show

app/views/questions/show.html.erbにて↓のように記述します。

<%= link_to 'Delete', question_answer_path(@question, answers),method :delete, data:{ confirm: 'Are you sure?' } %>

事例① question_id のみが必要な場合
/questions/:question_id/answers
→ URIに渡すパラメーターは、:question_id の1つ。

事例② questionとanswer が必要な場合
/questions/:question_id/answers/:id
→ URIに渡すパラメーターは、:question_id 、(answerの):idの、2つとなる。

app/controllers/answers_controller.rbにて↓のように記述します

def updateの↓に作成

def destroy
  @question = Question.find(params[:question_id])
  @answer = @question.answers.find(params[:id])
  @answer.destroy
    redirect_to question_path(@question), notice: 'Deleted!'
end

@question = Question.find(params[:question_id]←question_idにしないと
AnswersController#destroyのActiveRecord :: RecordNotFound
「id」= 9の質問が見つかりませんでした
↑のようになるので注意します。

36:QuestionsControllerのリファクタリング

app/controllers/questions_controller.rbにて↓のように記述します。

class QuestionsController < ApplicationController

before_action :set_question, only: [:show, :edit, :update, :destroy]

  def index
    @questions = Question.all
  end

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

  def new
    @question = Question.new
  end

  def create
    @question = Question.new(question_params)
     if @question.save
      redirect_to root_path, notice: 'success!'
     else
    flash[:alert] = 'Save error!'
   render :new
  end
 end

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

  def update
  # @question = Question.find(params[:id])
     if @question.update(question_params)
      redirect_to root_path, notice: 'Success!'
     else
     flash[:alert] = 'Save error!'
     render :edit
  end
 end

  def destroy
  # @question = Question.find(params[:id])
    @question.destroy
    redirect_to root_path, notice: 'Success!'
  end
 
  private

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

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

37:デプロイの準備

Gemfileに以下の記述を追加

gem ‘sqlite3’, ‘~> 1.3.6’を↓にカットペースト

group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
  gem 'sqlite3', '~> 1.3.6'
end

これで開発とテストの時のみ作動するようにしました。

group :production do
  gem 'pg', '~> 0.18.4'
end

本番環境のときでrails_projectsの実行するときには
このGemを読み込むという設定pgはポスグレ(PostgreSQL)を使うためのgem

bundle install --without production

こうすることでproduction以外のgemをインストールできます。
ターミナルではDevelopmentモードで動いています。
productionモードで動くのはHerokuのサーバー上です。

less .bundle/config
BUNDLE_WITHOUT: “production”設定が書かれるので
今後bundle installする時はbundle installでよくオプションは付けなくても大丈夫です。

database.ymlの設定インデントが重要なことに注意してください!
config/database.ymlにて↓のように記述します。

production:
  <<: *default
  adapter: postqresql
  encoding: unicode

ポスグレに接続するという設定
日本語も使えるunicodeにするという設定
assetのプリコンパイルを有効にするという設定

config/environment/production.rbで↓のように記述します。

config.assets.compile = true

↑アセットのプリコンパイルではCSSやJSのファイルを一つにして圧縮したり
画像ファイルを整理したりしてユーザーが
高速にページを読み込めるようにデプロイ時に準備を行います。

config/routes.rbにてルートページが設定されているか確認します。ないとエラーになります。
root ‘questions#index

38:Gitの設定

① – Git : global configの設定Gitで、個人の識別情報を登録する必要があリます。

git config --global user.name "suzu"
git config --global user.email bou@example.com
#gitを初期化
git init

管理するファイルの選択を行います。
この場合gitignoreファイルを除いた全て(qandaファイル配下)

git add -A

show hiddenファイルでgitignoreファイルは見ることができる
メッセージをつけてコミットします。

git add -A
git commit -m "Initial commit"
#ファイルを更新したら毎回行う。
git commit -m "Initial commit"

39:Heroku CLIのインストール

Cloud9などからHerokuを操作するためのツール
CLI(Command Line Interface)

~/environmentでターミナルで以下をコマンドします。

curl -OL https://cli-assets.heroku.com/heroku-linux-x64.tar.gz

このURLでダウンロード↑するという意味

ls
heroku-linux-x64.tar.gz rails_projects README.mdruby_projects

圧縮ファイルを解凍します。↓

tar zxf heroku-linux-x64.tar.gz

ls
heroku heroku-linux-x64.tar.gz rails_projects README.md ruby_projects

ls heroku
bin lib node_modules package.json yarn.lock
CHANGELOG.md LICENSE oclif.manifest.json README.md

herokuを移動します。

sudo mv heroku /usr/local

一般的にシステム管理者が↑自分でコンパイルしたアプリケーションをインストールする場所

ls /usr/local/heroku
bin lib node_modules package.json yarn.lock
CHANGELOG.md LICENSE oclif.manifest.json README.md
echo 'PATH=/usr/local/heroku/bin:$PATH' >> $HOME/.bash_
echo 'PATH=/usr/local/heroku/bin:$PATH' >> $HOME/.bash_profile
Path=/usr/local/heroku/bin:$PATH#←という文字列を
ユーザーホームディレクトリにある.bash_profileと言うファイルの内容に追記

.bash_profileとは?シェルの設定ファイルのこと。

シェルは人間からコンピュータに命令を伝えるための仕組み

設定したパスの反映↓

source $HOME/.bash_profile
function
↑のようになればOK

バージョンの確認

heroku -v
heroku/7.39.1 linux-x64 node-v12.13.0

↑のようになればOK
圧縮ファイル削除

rm -f heroku-linux-64.tar.gz

40: RailsアプリとHerokuの関連付け

cd rails_projects/qanda/

Herokuにログイン

heroku login --interactive

メアドとパスでログイン

RailsアプリとHerokuの関連付けをする

heroku create qanda-ユーザー名

アプリ名は入力しないとデフォルトになる(思いつかなければ使う)
URLにも使われるので注意!記号&や_でエラーが発生したので
出来るだけ使わないほうが無難?

41:デプロイ

cd ~/environment/rails_projects/qanda

git push heroku master

この記述だけでソースコードをサーバーにデプロイしてくれる

次にデータべースのマイグレーションを行う
開発環境で使っていたコマンドにheroku runをつける

heroku run rails db:migrate

URLを確認

heroku apps:info
Web URL: https://qanda-ユーザー名.herokuapp.com/

URLにアクセスしてテストしよう!

42:アプリの削除方法

不必要に開発したアプリをインターネット上に公開したまま
放置するのはセキュリティ上まずいのでアプリの削除を行う

heroku apps:infoでアプリ名を見る
=== qanda-ユーザー名

削除するコマンド–app アプリ名

heroku apps:destroy –app qanda-ユーザー名

> qanda-ユーザー名
アプリ名で削除

URLにアクセスし使えなくなっていることを確認したら完了

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です