RailsアプリをAWS EC2にデプロイする方法その①下準備編

はじめに

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

先日自身初となるポートフォリオを完成させました!

そしてAWSを使って本番環境にデプロイさせたので今回はその方法を簡潔に分かりやすく4段階にわけて書いて行きます。

1・下準備編⇦今回ここ

RailsアプリをAWS EC2にデプロイする方法その①下準備編 - 21歳フリーターからrailsエンジニアになるまで

2・DB.サーバー構築編

RailsアプリをAWS EC2にデプロイする方法その②DB.サーバー構築編 - 21歳フリーターからrailsエンジニアになるまで

3・デプロイ編①

RailsアプリをAWS EC2にデプロイする方法その③デプロイ編① - 21歳フリーターからrailsエンジニアになるまで

4・デプロイ編②

RailsアプリをAWS EC2にデプロイする方法その③デプロイ編② - 21歳フリーターからrailsエンジニアになるまで

 

少しでも僕と同じ境遇の人の役にたてたら光栄です。

 

また、今回はこちらの記事を参考にしました。同じような内容になってしまいますが初学者なりに簡潔に書いてくことを心がけます。

qiita.com

今回はCHARMEという仮想のアプリをデプロイして行きます。

それじゃ、レッツラゴー!!

 

1・VPCの作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

f:id:yamasey712:20191012131355p:plain

まずは、AWSという広い広い土地の中から自分専用の土地を作ります。

この自分専用の土地の中に環境を構築していくイメージです。

 

トップ画面より「VPC」をクリックして

詳細ページの左上「VPCの作成」をクリックしてください。

f:id:yamasey712:20191012132220p:plain

入力する項目が出てきますので

それぞれに

ネームタグ:VPC_for_CHARME (なんでも良いよ)

CIDRブロック:10.0.0.0/16

テナンシー:デフォルト

 このようにします。

いい調子だ(^ ^)

 

2・サブネットの作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

f:id:yamasey712:20191012132925p:plain

サブネットとは、一言で言えば 「ネットワークグループ」 といったところでしょうか。

「これらは外部との通信だけを行う」「これらは内部通信だけを行う」
といった具合に、同じVPCの中でも役割の異なるいくつかのグループが出来上がります。
このグループを「外部接続グループ」「内部接続グループ」といった具合に単位毎に分けてくれるものが、サブネットと呼ばれます。

f:id:yamasey712:20191012133113p:plain

 

ここでの入力は4つ!!

ネームタグ:subnet_for_CHARME(なんでも良いよ)

VPC:さっき作ったVPCを選択

アベイラビリティーゾーン:ap-northeast-1a

CICRブロック:10.0.0.0/24 

 

このアベイラビリティーゾーンは選択するリージョンによって違いますが、よっぽどのことがない限り「アジアパシフィック(東京)」を選択し進めて行きましょう。

リージョンはログイン後の右上の部分で選択できます。

 

3・インターネットゲートウェイの作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

f:id:yamasey712:20191012133907p:plain

インターネットゲートウェイとは名前の通り「インターネットの入り口」にあたります。

1で作成したVPCは、あくまでAWS内での占有領域です。

外部との接続を行う際は、その領域から外に出ていかなければなりません。
その窓口となるのが、今回のインターネットゲートウェイなのです。

f:id:yamasey712:20191012135016p:plain

ここでの作業はいたって簡単で2ステップです

ゲートウェイの名前を決める

ネームタグ:gateway_for_CHARME 

 ②ゲートウェイVPCを紐づける

「アクション」をクリックし「VPCにアタッチ」を選択

さっき作成したVPCを選択

 

状態の欄が赤色の文字から、緑色で「attached」に変化したかと思います。

これにてインターネットゲーウェイの作成は終了です!

 

疲れてきた??頑張ろう!

 

4・ルートテーブルの作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

f:id:yamasey712:20191012135720p:plain

ルートテーブルは、 通信に関するルールブック みたいなものです。

「この場合はこっちに通信を送る」「この場合はこっち」
みたいなものをまとめたものがルートテーブルです。

 

f:id:yamasey712:20191012135942p:plain

ここまでくるとやることが一緒ですね。

名前タグ:table_for_CHARME

VPC:作ったやつを選択 

 

そしてこのルートテーブルに、
「インターネットゲートウェイをルーティングするというルール」を記載したいと思います。

作成したルートテーブルを選択した状態で、
下のタブ「ルート」を選択し、
「ルートの編集」を選択します。

 

f:id:yamasey712:20191012140817p:plain

すると、新たな入力欄が出ますよね?

送信先:0.0.0.0/0

ターゲット:先ほど作成したゲートウェイ 

 このように設定し保存ボタンをクリックします。

 

そして最後にサブネットとの紐づけになります。

1・サイドバーの「サブネット」を選択

2・関連づけを変更するサブネットを選択

3・画面下のルートテーブル選択

4・編集

5・先ほど作成したルートテーブルを選択

6・保存 

こんな感じで紐付けを行います!

 

5・セキュリティーグループの作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

f:id:yamasey712:20191012141348p:plain

下準備編もラストになりましたので頑張りましょう!!

 

セキュリティーグループは、 セキュリティーに関するルールを記載したもの です。

「この通信は許可」「この通信は拒否」といった具合に、
適応されたグループ毎にルールを設定できます。

 

サイドバーのセキュリティグループを選択し作成をスリック

f:id:yamasey712:20191012141814p:plain

入力する項目は3つ

セキュリティーグループ名:CHARME_securitygroup

説明:セキュリティーグループ名と同じ名前でいいよ
VPC:さっき作ったVPC

 ここら辺はすんなり行きましょう!

 

次はルールの設定です。

ここからなんだかややこやしくなってくる所ですが、ここでは解説なしで簡潔に書きますので解説が必要な方はググってくだいな(ごめんなさい(涙))

1・作成したセキュリティーグループを選択

2・下のインバウンドルールを選択

3・ルールの編集を選択

ここからルールを記述していきますよ!

2種類を記述します。

タイプ:SSH

プルトコル:自動選択

ポート範囲:自動選択

ソース:マイIPを選択*自動で ***.***.***/32をやってくれる 

 

タイプ:HTTP

プルトコル:自動選択

ポート範囲:自動選択

ソース:カスタムを選択し0.0.0.0/0を記述

 

ここでは詳しく解説はしませんがこれにて下準備編は終了です!!

お疲れ様でした!!

次はDB.サーバー構築編です!!頑張っていきましょう!!

 

次章:DB.サーバー構築編

Rails未経験者の初ポートフォリオ

さて、先日やっと自身初のポートフォリオが完成しました!!!(涙)

それがこちらです!!

 

テーマは魅力を共有しましょう!!っていうアプリです。

 

ポートフォリオhttp://54.95.23.50/

GitHubhttps://github.com/yamasey/CHARME

 

じゃん!!!!ってドヤ顔できるほどの作品では無いけど頑張りました。(涙)

計1ヵ月ちょっと掛かってしまいました(ハマりにハマったので笑)

この1ヵ月は『よーし!!』と『おいおいまたかよ(涙)』の繰り返しでした。

 

ということで今回は僕のポートフォリオ製作の苦戦した点を書いていきます!!

 

苦戦した点

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

僕は大きく3つの部分で苦戦しハマりまくって泣きそうになりました。笑 

  1. 環境構築
  2. Devise周辺
  3. AWSでのデプロイ

 

1. 環境構築

僕ははじめはRails6のバージョンで開発を進めようとしました。

しかし何やら6からはWebpackerならぬものが導入されたみたいでプラグインをなんとかしろ!!って何回も怒られてしまいここで詰まるくらいならバージョンを下げようということでRails5のバージョンで開発を進めていきました。

 

2. Devise周辺

Deviseは調べれば割と簡単に実装はできてしまします。しかし実装できる機能が多彩すぎるので初学者は多少苦労するかもしれません。

僕は実装の部分では苦労しませんでしたが、なぜかサインナップとログインをしようとすると読み込み状態が続くバグに見舞われ5日ぐらいハマりました。(いきなり治った)ここは流石に参考資料などがなかったため心が折れそうになりました。。

 

3. AWSでデプロイ

これが自分にとっての最大の山場でした。

時間にして約1週間かかりました。(涙)

本当に何度herokuで妥協しようかなと思ったことか。

 中でもAWSの環境構築と画像投稿の部分でハマりまくりました。

環境構築の部分はコンピュータ側の知識も必要となってくるためググりまくってなんとかデプロイに成功しました。永遠にページが読み込めません。から画面が本番環境に自分のアプリのページが出た時には死ぬほど嬉しかったです。

喜んだのもつかの間S3を使った画像投稿機能もかなりハマり泣きそうになりました。

グーグルには本当にお世話になりましたよ。

(時間があればデプロイの仕方のブログもあげますね)

 

なんでAWS

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

 これはいたってシンプルで差別化をしたかったからです。

一番初めは大体の人がherokuでデプロイをすると思います。

ここで AWSでデプロイをすることで少しでも採用する方が『お?』となってくれればと思い難易度は高かったですが頑張りました。

 

最後に

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

ここで終わったわけではなく最後の一番大事な部分の就活があります。

自分の納得できる会社に入れるよう最後まで気を抜かずに頑張っていきます。

 

 

プロフィールを書きますよ

すごく久しぶりになってしまった。

『忙しいのは理由にならない!』と言われてしまったら終わりですが定期的に書かなくちゃいけないですね。

ということで今回は自分のプロフィールを詳しく書いていきます。

誰得なのかは分かりませんが、もしみた方はこんな人なんだなぁぐらいに思っていてください。笑

 

簡単な自己紹介

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

・1998年7月12日生まれの21歳

 

静岡県浜松市三ヶ日町という田舎で育つ(田舎だけどとてもいい町)

 

・小中高と野球に捧げる(ポジションはずっとセンター)

 

・高校卒業後は大学に行かずオーストラリアに行ったり劇団四季で働いてみたりとやりたいことをやりたいだけしいた。

 

・そして現在エンジニアとして就職活動をスタートさせる(なんか決意表明みたい)

 

とまぁ簡単にまとめるとこんな感じです。。。よくいそうですね。笑

 

なんで大学に行かなかったの??

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

いい質問ですね。(自作自演だよね)

 理由は大きく2つあります。

 

1つ目は母子家庭だったからです。

いわゆる『金銭的に。。。』みたいな感じでよくあることですね。

これは言ってしまえば単なる後ずけのような物なのでそこまで自分の中で辛かったなどの気持ちはありません。

 

2つ目は大学というものに価値を見出せなかったことです。

これが自分の中で1番大きな理由でした。

それまでは大きな『夢』がありませんでした。このまま高額な学費も払って理由もなしにただ大学に進学するだけの自分を想像した時に、絶対4年間が何も得られずに終わってしまうなと思い大学に行く。という気持ちは早い段階から消えてました。

 

じゃあ何してたの??

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

いい質問ですね。(これも自作自演)

 

まず前提として、大学に行かなくて本当によかったと思っています!大学に行っていたら決してできなかった経験を詰めたからです。

 

高校3年生の夏。10年続けた野球に一区切りがつき今後のことを考えた時に『大学には興味ないけど海外には興味がある』ということで、高校卒業後6ヶ月間アルバイトをして10月からオーストラリアへ1人スーツケース1つでいきました。

ここでは数えきれないほどの刺激を受けました。

全てが新しいことで毎日が楽し行くて充実した日々を過ごせました。今まで当たり前だと思っていたことがこっちでは常識でなかったり、全く違う考えを持った人たちと関わることで自分の中での教養が育ちました。

また、自発的になんでも行動する力が身につきました。

この経験と生い立ちがあったからこそ後にエンジニアを目指すきっかけにもなることができたので決して間違った事はしてないと信じてます!

 

なんでエンジニア??

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

きっかけはささいな事でした。

僕は堀江貴文さんが昔から好きでよく動画を見ていました。

そしてあの日も何気なく動画を見ているとその日はエンジニア(Progate) の会社の代表とのコラボ動画を出していました。

見ているとプログラミングの事について話していたりとても面白い内容でした。

そして僕もやってみたい!!と思い始めたのが全ての始まりでした。(6月ぐらいだったかな)

そして、進めていくうちにさらに理解、関心が深まり、エンジニアという職業は自分のやりたいサービスを自分の手で作り上げていけるすごく面白い仕事だなと思うようになりました。

 

本当にエンジニアという仕事を知り興味を持ててよかった(涙)

 

最後に

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

先日就活用のポートフォリオが完成しいよいよ完成したのでこれからエンジニアになるべく頑張っていきます!

僕自身にとって初めてやりたい!と心から思える仕事に出会えたので頑張ります!

Rails+Ajax+コメント機能を実装! Railsポートフォリオ制作日記②

日記のくせに書く頻度が少ないかな。

という事で、コメント機能を実装してみたのでまとめていきます。

レッツゴー

またこちらの記事を参考にしてほとんど一緒になってしまいましたが自分なりに書いたのでご了承ください。

ysk-pro.hatenablog.com

 

前提

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

前提として、投稿詳細ページへのコメントを実装しました。

デザインもやっていないのでカスタマイズは自分流にアレンジして下さいね。

完成イメージはこんな感じです!

f:id:yamasey712:20190917020520p:plain

コメント機能

 

また、コメントを表示するページ(僕の場合はshowページ)の実装と、JQueryの読み込みはできてる前提で行きます!

 

2 コメントテーブル作成

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

$ rails g model comment content:string user:references micropost:references

 UserモデルとMicropostモデルと関連づけるためreferencesも書く。

config/db/schema.rb

create_table "comments", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
  t.string "content"
  t.bigint "user_id"
  t.bigint "micropost_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.index ["micropost_id"], name: "index_comments_on_micropost_id"
  t.index ["user_id"], name: "index_comments_on_user_id"
 end

 

 うん。しっかりとuser_idとmicropost_idがある。

ちなみに、『micropost_id』がどの投稿に対するコメントであるかを格納するため

『user_id』が誰の投稿であるかを格納するためになります。

安心できたところで忘れずに

$ rails db:migrate 

 

3 モデルの設定 

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 

app/models/comment.rb

class Comment < ApplicationRecord
belongs_to :user
belongs_to :micropost
validates :content, presence: true
end

 例えばコメント①はただ1人のユーザーとただ1つの投稿に結びつく1対1の関係であるため『belongs_to』で結びつけます。

 

app/models/user.rb

class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :comments, dependent: :destroy

 

app/models/micropost.rb

class Micropost < ApplicationRecord
belongs_to :user
has_many :comments, dependent: :destroy

 

逆にUserモデルやMicropostモデルは1人のユーザーが何個もコメントする事ができ、1つの投稿は何個もコメントを持つ事ができる1対多の関係であるため『has_many』で結びます。また、『dependent: :destroy』は投稿が消えたらコメントもついでに消してね。って伝えてます。

 

4 ルーティング

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

config/routes.rb

resources :microposts, only: [:new, :show, :index, :create, :destroy] do
  resources :comments, only: [:create, :destroy]
 end

 コメントがどの投稿にされたかを識別するため、ルーティングのURLに投稿のIDが

必要になります。つまり『/micropost/1/comment/』こんな感じにしたい。

そのためにはルーティングをこのように記述する必要がある。(ネストすると言う)

ちなみにこの1は『micropost_id』のこと。

 

5 コメントコントローラー

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

app/controllers/comment.rb

class CommentsController < ApplicationController
 def create
  @micropost = Micropost.find(params[:micropost_id]) #1
  @comment = @micropost.comments.build(comment_params) #2
  @comment.user_id = current_user.id #3
  if @comment.save
  render :comments #4
  end
 end

 def destroy
  @comment = Comment.find(params[:id]) #5
  if @comment.destroy
  render :comments #6
  end
 end


 private
  def comment_params
   params.require(:comment).permit(:content)
  end
end

 

#1:コメントをする対象の投稿(micropost)のインスタンスを作成します。

#2:「.build」を使うことで、@micropostのidをmicropost_idに含んだ形でcommentインスタンスを作成します。

#3:現在のuserのidを入れます。

#4:保存がされると、render :commentsによって「app/views/comments/comment.js.erb」を探しにいきます。
「form_with」でフォームを送信した時は、デフォルトでjsファイルを探しにいく設定になっています。
htmlファイルを探しにいってほしい場合には、form_withの後に「local: true」と記載する必要があります。

#5:削除する対象のコメントインスタンスを探します。

#6:削除がされると、「comments.js.erb」を探しにいきます。
削除のリンクを記載している「link_to」の中に「remote: true」を記載していることでjsファイルを探しにいってくれます。
7. app/views/comments/_comments.html.erb に記載しています。
「remote: true」を記載していなかった場合は、htmlファイルを探しにいきます。

 

6 投稿のコントローラー

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

app/controllers/microposts_controller.rb

def show
@micropost = Micropost.find(params[:id])
@comment = Comment.new #1
@comments = @micropost.comments #2
end

 

どちらも、7. 投稿のビュー「app/views/microposts/show.html.erb」でパーシャルに渡す変数として使用します。
#1:入力フォームで使用するインスタンスを作成しています。

#2:コメント一覧表示で使用するためのコメントデータを入れています。

つまり下準備の段階です。

 

7 投稿のビューページ

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

app/views/microposts/show.html.erb

<div>
<h4>コメント</h4>
<div id="comments_area"> #1←こいつがのちに重要になる
  #コメント一覧を表示させるrender#
<%= render partial: 'comments/comments', locals: { comments: @comments } %>
</div>
<% if user_signed_in? %>
#コメント入力フォームを表示させるためのrender#
<%= render partial: 'shared/comments_form', locals: { comment: @comment, micropost: @micropost } %>
<% end %>
</div>

 

#1:「id="comments_area"」がポイントです。
このidをターゲットにして、このdiv内をAjaxで書き換えます。
このdivの内側に、renderを使ってパーシャルを表示します。
@commentをパーシャル内で使うローカル変数commentとして渡しています。

 

8 パーシャル部分のビュー

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

app/views/comments/_comments.html.erb

<% comments.each do |comment| %>
<% unless comment.id.nil? %>
<p><%= link_to "#{comment.user.name}さん", "#" %></p>
<p>コメント:<%= comment.content %></p>
<% if comment.user == current_user %>
<p><%= link_to 'コメントを削除する', micropost_comment_path(comment.micropost_id, comment.id), method: :delete, remote: true %></p>
<% end %>
<% end %>
<% end %>

 

先ほど投稿のビューで渡したローカル変数(comments)をeach分で渡してあげてコメントがあれば全てを表示させるようにします。

ポイントは、コメントの削除のところで「(comment.micropost_id, comment.id)」と投稿のidとコメントのidを渡す必要があることと、5. コメントコントローラーのところでも触れましたが「remote: true」をつけることによって、コントローラーでjsファイルを探しにいってもらうことです。
idをcomment.micropost_idとcomment.idの2つ渡す必要があるのは、削除したいコメントを指定するには「micropost/1/comment/1」のようにmicropost_idとcomment_idを指定する必要があるためです。

app/views/comments/comments_form.html.erb

<%= form_with(model: [micropost, comment] ) do |form| %>
<div>
<%= form.text_area :content %>
</div>
<div class="actions">
<%= form.submit "コメントをする" %>
</div>
<% end %>

 ポイントは、「model: [micropost, comment]」とすることです。
micropost, commentはそれぞれ、7. 投稿のビューで渡しているインスタンスのローカル変数です。
投稿に紐づいたコメントを生成するため、ここでpost、microcommentのインスタンスを渡すことが必要になります。

 

9 jsファイル

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

app/views/comments/comments.js.erb

$("#comments_area").html("<%= j(render 'comments', { comments: @comment.micropost.comments }) %>")
$("textarea").val('')

 

このファイルに、7. 投稿のビューの中で id = "comments_area"とした箇所を書き換える処理を記載しています。

「$("#comments_area")」が id = "comments_area"をターゲットとする記載です。
ターゲットとした箇所を、「render 'comments'」で指定している8. パーシャル部分のビューの内容で書き換えています。

{ comments: @comment.micropost.comments }で、@comment.micropost.comments をローカル変数 comments に入れて渡しています。
@comment.micropost.comments は、コメント一覧表示するのに必要なコメント全件です。

「$("textarea").val('')」によって、コメント入力後のコメント入力欄を空にしています。

 

10 最後に

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

ほとんど書いてあること同じじゃねーかあ!!って言われても仕方ありませんがこれはあくまで自分自身が忘れないためにまとめていますので大目にみてください。

おそらく、この通りにやってもうまくいかないこともあると思います。

そんなことで諦めず、あーでもないコーデもないと試行錯誤しながらやっていくうちに機能するようになります。(きっとね)

その達成感と行ったら一人でガッツポーズしちゃうぐらいだから相当嬉しいよね。

だからやめられない。

という事でこれ書いてたらもう夜中の3時だから寝なきゃだね。

それじゃあおやすみ