- 投稿日:2020-11-26T23:41:04+09:00
Rails結合テスト ログイン処理まとめ
はじめに
Railsでオリジナルアプリ制作を終えました。モデルの単体テストは完了したものの、結合テストは未実施でした。ユーザーがログインしないと使えない機能テストにおいて、ログイン処理を繰り返しテストコードに記述するのは避けたいと思います。より簡素な記述をするため、書き記します。
開発環境
ruby 2.6.5
Rails 6.0.3.4
Gem : gem 'rspec-rails'目次
1.ログイン処理
2.簡素なログイン処理の記述1.ログイン処理
ログインするにあたり、email及びパスワードが必要だと仮定する。テストコードにおける記述は以下のようになる。問題は機能テストごとにログイン処理を書く必要がある。これを簡略化する方法を次の節で説明する。
spec/system/○○_spec.rbvisit root_path fill_in 'user_email', with: user.email fill_in 'user_password', with: user.password click_on("Log in") expect(current_path).to eq root_path #以下ログインした状態での機能テストの記述を書く visit new_desk_path※なお、email入力フォームのidはuser_email、パスワードはuser_passwordとする。
2.簡素なログイン処理の記述
specディレクトリの直下にsupportディレクトリを作成する。さらにその直下にsign_in_support.rbファイルを作成し、下記ログイン処理のメソッドを作成する。
spec/supports/sign_in_support.rbmodule SignInSupport def sign_in(user) visit new_user_session_path fill_in 'email', with: user.email fill_in 'password', with: user.password find('input[name="commit"]').click expect(current_path).to eq root_path end endここで定義したsign_inメソッドをテストコードのファイルで使用できるように下記を設定する。
spec/rails_helper.rb# コメントアウトを外す Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } # 中略 RSpec.configure do |config| # 追記 config.include SignInSupport以上によりsign_inメソッドを使用できるようになった。下記に使用例を示す。
spec/system/○○_spec.rbbefore do #テスト用のユーザーダミーデータを生成する。 @user = FactoryBot.create(:user) end context '画像投稿ができるとき'do it 'ログインしたユーザーは新規投稿できる' do # ログインする sign_in(@user) #以下省略以上
- 投稿日:2020-11-26T23:25:46+09:00
deviseのgemで、ユーザーの詳細ページや編集ページは作れないかなぁ…
はじめに
deviseをを使ってユーザー管理機能を実装した。マイページを作って編集をできるようにしたい。しかし、deviseのコントローラーでできるのか、不安だったので、deviseで作ったuserディレクトリの配下には作らず、別でuserコントローラーを作った。似たようなディレクトリとファイルがあるので、なんかモヤモヤする。
userコントローラー
ターミナルで、
rails g controller users
を行うと、
controllers/users_controller.rb
ファイルが生成される。users_controller.rbclass UsersController < ApplicationController def show @user = User.find(params[:id]) end endまあ、こうすれば詳細ページを作れるのだが…
終わりに
deviseのコントローラーにはコメントアウトされている部分がたくさんあるが、この中に詳細を表示させたり、編集したりすることは
- 投稿日:2020-11-26T22:47:55+09:00
cloud9でrails sを終了せずに閉じてしまった時の対処法
はじめに
cloud9でrails sを終了せずにターミナルを閉じてしまいました...
再度rails sをするとこんなエラーが...A server is already running. Check /home/ubuntu/environment/[フォルダ名]/tmp/pids/server.pid.pidファイルを開いてみるも5桁の数字が記載されているだけ...
下記の記事を見つけて再起動するも上手く行かず。A server is already running 対処方法【Rails】
pidファイルを削除しようとするもファイルツリーから見つけられず...
上記エラー文から開いたpidファイルの数字を削除して再度rails sしました。
すると今度は違うエラー文...Address already in use - bind(2)解決法
下記の記事通り
Cloud9上でRails sをしてA server is already runningが出た時の対処法
$ kill -9 数字(pidファイルに記載)で済むはずなんですが、今回は数字を消してしまったので...
$ killall -9 rubyで解決しました?
参考:Address already in use - bind(2) when starting server in Cloud9 IDE
- 投稿日:2020-11-26T21:51:07+09:00
Ruby ハッシュとシンボルの記法 まとめ
Railsチュートリアル
ハッシュとシンボルの書き方user = {} # {}は空のハッシュ
=> {}
user["first_name"] = "hurihata" # キーが "first_name" で値が "hurihata"
=> "hurihata"
user["last_name"] = "koyo" # キーが "last_name" で値が "koyo"
=> "koyo"
user["first_name"] # 要素へのアクセスは配列の場合と似ている
=> "hurihata"
user # ハッシュのリテラル表記
=> {"last_name"=>"koyo", "first_name"=>"hurihata"}ハッシュのキーとしてシンボルを採用する場合、user のハッシュは次のように定義できる
一つめの記法
user = { :name => "koyo", :email => "kkkk@XXX.com" }
=> {:name=>"koyo", :email=>"kkkk@XXX.com"}
user[:name] # :name に対応する値にアクセスする
=> "koyo"
user[:password] # 未定義のキーに対応する値にアクセスする
=> nil二つめの記法
{ name: "koyo", email: "kkkk@XXX.com" }
自分的にはハッシュロケット(=>)を使う一つ目の記法より二つ目のシンボルの:を後ろにつける記法の方が見やすく使いやすいと感じた。
- 投稿日:2020-11-26T20:44:38+09:00
ancestryはawsにデプロイしただけでは使えない
1.どんな状態だったか
ancestryを利用して、カテゴリー機能を実装、ローカルでは動くのに本番環境で反映されないという状態
2原因
ancestryを使うためには、本番環境でもローカルと同じ様に
db migrateし、seedを読み込まなくてはならない3解決方法
まずdb migrateします
$ cd var/www/app名/current $ rake db:migrate RAILS_ENV=production上手くいかない時はdbをドロップしもう一度クリエイトし直す
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop $ rake db:create RAILS_ENV=productionもう一度migrateします。
次にseedを反映させます。
$ rake db:seed RAILS_ENV=production以上になります。
4最後に
自動デプロイをしている場合はcurrentディレクトリで操作を行う必要があるそうです
そうでない場合は~ディレクトリで大丈夫みたいです参考にした記事
[aws,rails]ancestryをawsにデプロイした時に反映されない状況の解決方法
本番環境でrake db:seedを実行する際の注意点
- 投稿日:2020-11-26T18:56:48+09:00
MySQL 5.5から5.7へのバージョンアップと、libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解消
はじめに
前回の記事 Cloud9でRuby on Railsの環境構築 ~インストールから起動まで~ で「Yay! You’re on Rails!」を表示し、最低限の環境構築までは完了したが、MySQLのバージョンが古かったためバージョンアップをすることに。
その過程でいくつかエラーが発生したので、備忘録のためにカキカキしていきます。
目標
MySQL 5.5 からMySQL 5.7にアップデートし、「Yay! You’re on Rails!」を表示させる
環境
Amazon linux
ruby 2.6.3
Rails 6.0.3.4
MySql 5.5.62やっていきましょう
MySQLのバージョンアップ
まずはバージョンを確認しておきます。
$ mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 Server version: 5.5.62-log MySQL Community Server (GPL) ~略~そうしたら"yum"を使ってMySQL関連のモジュールをアンインストール。
その後使用するバージョンを指定して、MySQLのモジュールをインストールします。$ yum remove mysql* $ yum install mysql57 mysql57-devel mysql57-serverここで一度バージョンを確認してみます。
$ mysql -u root -p Enter password: ERROR 2002 (HY000): Can't connect to local MySQL server through socket'/var/lib/mysql/mysql.sock' (2)エラーが発生。前回の記事と同じ内容です。
socketファイルが無いためMySQLに接続できていないので、MySQLを再起動してsoketファイルを自動作成させます。
その後もう一度バージョンを確認。$ sudo /etc/init.d/mysqld restart $ mysql -u root -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 4 Server version: 5.7.31 MySQL Community Server (GPL)これでうまく5.7.31がインストールできました。
サーバー起動
サーバーを起動して接続できるか確認します。
$ rails s ~略~ libmysqlclient.so.18: cannot open shared object file: No such file or directory ~略~エラーです。
ディレクトリとかファイルがないから開けませんって言われています。今回はDBにMySQLを使用するため、プロジェクト作成時に"-d mysql"オプションを追加しました(前回の記事参照)。
この時にmysql2というgemがインストールされたのですが、これを再インストールすれば解消されるっぽい。そんなわけでmysql2をインストールしなおします。
$ gem uninstall mysql2 $ gem install mysql2これで起動してみましょう。
$ rails s Mysql2::Error::ConnectionError Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)またsoketファイルか・・・
MySQLを再起動してから再びサーバーを起動。$ sudo /etc/init.d/mysqld restart $ rails s成功しました。
- 投稿日:2020-11-26T18:02:34+09:00
サルでもできる!? Rails6アプリをAWS EC2にデプロイするまでの全手順【後半】(独自ドメイン, HTTPS化, S3, CloudFront)
この記事では,画像投稿機能の付いた
Rails 6
のアプリをAWS EC2
にデプロイするまでの全過程を解説します。【前半】 でRailsアプリのデプロイはひとまず完了しましたが,まだまだすべきことがたくさんあります。続きも気を抜かずに頑張りましょう!
章 タイトル 【前半】 1章 はじめに 2章 VPC 3章 RDS 4章 EC2 5章 サーバー構築 6章 デプロイ(Capistrano) 【後半】 <-- こちら 7章 独自ドメイン 8章 HTTPS化(ACM, ALB) 9章 デプロイ関連事項 10章 S3 11章 CloudFront 12章 削除方法 7. 独自ドメイン
Railsアプリを公開することができましたが,現状では2つ大きな問題を抱えています。
- サイトの URL が不自然
google.com
のような独自ドメイン
ではない- HTTPSではない
- Google Chrome で「このサイトへの接続は保護されていません」という警告が出る
まずは前者から解決していきましょう。
aws-sample-app.com
のような URL でアクセスできるようにするには,ドメイン
を取得する必要があります。
ドメイン
は有料ですが,こだわらなければ初年度は数百円程度で取得できます。この記事では昔から代表的な
レジストラ
である「お名前.com」で取得する前提で解説します。7.1 ドメインの購入
「お名前.com」にアクセス
検索窓に取得したいドメイン名を入力し,「検索」ボタンをクリック
- ドメインに使用できる文字は「半角英数字」と「ハイフン
-
」です- 「アンダースコア
_
」 は使用できません
.com
などのドメインを選択し,「料金確認へ進む」ボタンをクリック
- 自動選択されているチェックを外し忘れないように注意しましょう
- こだわりがなければ初年度の安いドメインを取得してもよいでしょう
購入処理を行って下さい。「Whois情報公開代行」は必須ですが,その他のオプションは全て不要です
- 「サーバー」は「利用しない」をチェック
- 「Whois情報公開代行メール転送オプション」などは全てチェック不要
「お申し込みを受け付けました。」と表示されたら「ドメインの設定はこちら」のリンクをクリック
【備考】後に続きの操作をおこないますので,他のタブで続きの作業を進めて下さい
自動更新の解除
初期設定では,ドメインの更新期限日を過ぎますと自動更新・自動課金されます。
2年目以降は料金が高くなるドメインが多いですので,自動更新を解除したい場合は以下の操作を行ってください。
「お名前.com」のページ上側にあるタブの「ドメイン」を選択
「更新画面から移動する」をクリック
アプリで使用するドメインを選択
- 「自動更新」ボタンをクリック
「確認画面へ進む」をクリック
「自動更新設定申込内容」の項目が「解除する」になっていることを確認の上,「規約に同意し、上記内容を申し込む」ボタンをクリック
「解除する」ボタンをクリック
「ドメイン一覧」のタブをクリック
【備考】後に続きの操作をおこないますので,続きの作業は他のタブで進めて下さい
7.2 IPアドレスとドメインの関連付け
Route 53
を利用することで,先ほど購入したドメイン
をIPアドレス
に変換することができます。通常の使用範囲内ならば月100円もかかりません。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーンの作成」ボタンをクリック
キー 値 ドメイン名 取得したドメインを記載 説明 - オプション アプリ名_domain タイプ パブリックホストゾーン
「ホストゾーンの作成」ボタンをクリック
タイプが「NS」の方の「値/トラフィックのルーティング先」に表示されている4つを
ネームサーバー
としてメモしておいて下さい
- 【要注意】メモする際に,それぞれの最後についている「ドット
.
」は削除して下さい!7.3 ネームサーバーの変更
先ほど残しておいた「お名前.com」に移動して下さい
(タブを閉じてしまった場合は,再度「お名前.com」にアクセスし,ログインして下さい)
「ドメイン一覧」の中から取得した「ドメイン名」を選択
「ネームサーバー情報」の項目の「ネームサーバーの変更」をクリック
「2.ネームサーバーの選択」をクリック
「その他」タブをクリックし,「その他のネームサーバーを使う」の方にチェックを入れ,先ほどメモした4つの
ネームサーバー
をコピペして下さい
- 先ほど注意しました通り,最後についている「ドット
.
」は入力しないで下さい7.4 ネームサーバーの確認
ローカル環境のターミナルから以下を実行して下さい。
ローカル環境のターミナルdig ドメイン名 NS +short登録した4つのドメインが入っていればOKです。(順番が入れ替わっていてもOK)
デフォルトの2つしか入っていない場合は,しばらく待ってから再度先ほどのコマンドを実行しましょう。
7.5 ドメインの適用
AWS
のRoute 53
の先ほどの続きの画面から,「レコードを作成」をクリック「シンプルルーティング」にチェックを入れた状態で「次へ」ボタンをクリック
「シンプルなレコードを定義」ボタンをクリック
キー 値 レコード名 ※入力しない 値/トラフィックのルーティング先 「レコードタイプに応じた IP アドレス または別の値」をクリックし, Elastic IP
を入力レコードタイプ A これで準備が完了です。まずは,ローカル環境のターミナルから以下を実行して下さい。
ローカル環境のターミナルcurl -I ドメイン名
最初に
HTTP/1.1 200 OK
もしくはHTTP/1.1 302
が出れば正常です。前回は
Elastic IP
でなければアクセスできませんでしたが,今度はドメイン名
でアクセスできる状態になっています。ブラウザから
ドメイン名
でアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)8. HTTPS化(ACM, ALB)
次はこちらの問題に対処していきましょう。
- HTTPSではない
- Google Chrome で「このサイトへの接続は保護されていません」という警告が出る
【備考】
ELB
のApplication Load Balancer(ALB)
を利用しますので,月2000円程度の費用がかかります。8.1 ACM
HTTPS化
には,まず,SSL/TLS サーバー証明書
を取得する必要があります。
Let's Encrypt
で取得する方法が有名ですが,AWSを利用する場合はSSL/TLS サーバー証明書
をACM
で取得し,ALB
に関連付けるのが一般的な手法です。作業が楽で,更新の手間も不要になります。
ALB
と関連付けますので,ACM
自体は無料で利用できます。
AWS
の画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択「証明書のプロビジョニング」の「今すぐ始める」ボタンをクリック
「パブリック証明書のリクエスト」を選択した状態で「証明書のリクエスト」ボタンをクリック
「この証明書に別の名前を追加」をクリック
取得した「ドメイン名」と「*.ドメイン名」を入力
「次へ」ボタンをクリック
- 「DNS の検証」を選択した状態で「次へ」ボタンをクリック
タグ名 値 Name アプリ名_alb
「確認」ボタンをクリック
「確定とリクエスト」ボタンをクリック
「続行」ボタンをクリック
8.2 DNS検証用の CNAME レコード追加
- ドメインの欄のプルダウンを開き,「Route 53 でのレコードの作成」ボタンをクリック
- 2つ表示されていますが,どちらか片方のみでOKです
- プルダウンが表示されない場合は,一度リロードして下さい
- 「作成」ボタンをクリック
【注意】
8.3
は先に行っても問題ありませんが,8.4
以降の作業は,状況が「検証保留中」から「発行済み」に変わってから行って下さい8.3 ALB 用のセキュリティグループの作成
【構成内容】
クライアント
--(HTTP or HTTPS)-->ALB
--(HTTP)-->EC2
ELB
の内のALB
(Application Load Balancer) を使用し,先ほど取得したSSL/TLS サーバー証明書
を使用できるように設定していきましょう。
ALB
はEC2
の前にリクエストを受け,(一般には複数の)EC2
に分散します。このことを踏まえたセキュリティグループを作成しましょう。
画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択
EC2
画面左のメニューバーの「セキュリティグループ」を選択し,「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_alb_security_group 説明 アプリ名_alb_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」を2回クリック
キー 値 タイプ HTTP プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK
キー 値 タイプ HTTPS プロトコル TCP ※自動選択 ポート範囲 443 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK 「アウトバウンドルール」は
デフォルトの設定を削除した後
「ルールを追加」をクリックし,以下を追加
キー 値 タイプ HTTP プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース カスタム: アプリ名_ec2_security_group 説明 ※空白でOK 作成後に次の図のようにルールが定まっているかどうかを確認して下さい。
8.4 ロードバランサーの設定
画面左のメニューバーの「ロードバランサー」を選択
「ロードバランサーの作成」ボタンをクリック
「HTTP, HTTPS」の方の「作成」ボタンをクリック
■ 手順 1: ロードバランサーの設定
- 【基本的な設定】
キー 値 名前 アプリ名-alb ※ ハイフンに変更 他はデフォルト
- 【リスナー】
「リスナーの追加」ボタンをクリックし,「HTTPS」を選択
- 【アベイラビリティゾーン】
キー 値 VPC アプリ名_vpc アベイラビリティーゾーン 「ap-northeast-1a」を選択し「アプリ名_public_1a_subnet」を選択 アベイラビリティーゾーン 「ap-northeast-1c」を選択し「アプリ名_public_1c_subnet」を選択 「次の手順: セキュリティ設定の構成」ボタンをクリック
■ 手順 2: セキュリティ設定の構成
- 「証明書の名前」がアプリ用のドメインであることを確認し,「セキュリティグループの設定」をクリック
■ 手順 3: セキュリティグループの設定
- 「アプリ名_alb_security_group」を選択し,「次の手順: ルーティングの設定」ボタンをクリック
■ 手順 4: ルーティングの設定
- ターゲットグループ
キー 値 ターゲットグループ 新しいターゲットグループ 名前 アプリ名-target-group ※ ハイフンに変更 ターゲットの種類 インスタンス ※デフォルト プロトコル HTTP ※自動設定 ポート 80 ※自動設定
- ヘルスチェック
デフォルト設定でOK
「次の手順: ターゲットの登録」ボタンをクリック
■ 手順 5: ターゲットの登録
- 「インスタンス」欄から、「アプリ名_instance」にチェックを入れた状態で「登録済みに追加」ボタンをクリック
「次の手順: 確認」をクリック
「作成」ボタンをクリック
8.5 Route 53の設定を修正
ドメインを
EC2
から先ほど作成したALB
に割り当てるように設定を変更しましょう。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーン」をクリック
アプリで使用するドメインをクリック
- 「タイプA」の「ドメイン名」のレコードをクリックし,「編集」ボタンをクリック
- 「値/トラフィックのルーティング先」の箇所を変更して下さい
- 「Application Load Balancer と Classic Load Balancer へのエイリアス」を選択
- 「アジアパシフィック (東京) [ap-northeast-1]」を選択
- 「アプリ名-alb」を含むロードバランサーを選択
- 「変更を保存」ボタンをクリック
8.6 セキュリティグループの修正
ALB
経由でアクセスされるように変更したため,EC2
はALB
からのアクセスに限定すべきです。そのため,EC2
用のセキュリティグループを修正します。
AWS
の画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択画面左のメニューバーの「セキュリティグループ」を選択
「アプリ名_ec2_security_group」にチェックを入れ,「アクション」ボタンをクリックし,「インバウンドルールを編集」ボタンをクリック
- タイプが
HTTP
のものを全て削除し,「ルールを追加」をクリックし,以下を設定
SSH
は削除しないこと
キー 値 タイプ HTTP ソース カスタム: アプリ名_alb_security_group 説明 ※空白でOK
- 「ルールを保存」ボタンをクリック
8.7 Nginx の設定ファイルを修正
ALB
への接続に使用するプロトコルがHTTPS
であることを識別できるよう,Nginx
の設定ファイルを修正し,再起動しておきましょう。(こちらを実行しないと,例えば POST リクエスト時にエラーが発生します)
サーバー環境のターミナルsudo sed -i s/X-Forwarded-Proto\ http/X-Forwarded-Proto\ https/g /etc/nginx/conf.d/$APP_NAME.conf sudo service nginx restartそれでは,
HTTPS
でアクセスできるかを確認しましょう。まずはターミナルから以下を実行して下さい。ターミナル(ローカル側でもサーバー側でもOK)curl -I https://ドメイン名
最初に
HTTP/2 200
もしくはHTTP/2 302
が表示されれば正常です。次にブラウザからhttps://ドメイン名
にアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)ブラウザのURLの左隣に「鍵マーク」が表示され,アプリが問題なく開けばOKです!
8.8 HTTPS にリダイレクト
【参考】 https://aws.amazon.com/jp/premiumsupport/knowledge-center/elb-redirect-http-to-https-using-alb/
最後に,
HTTP
でのアクセスをHTTPS
にリダイレクトするように設定しましょう。
EC2
の画面左のメニューバーの「ロードバランサー」をクリック(「アプリ名-alb」を選択した状態で)「リスナー」タブをクリック
HTTP : 80
の方の 「ルールの表示/編集」をクリック
- 上の「鉛筆」マークをクリックし,下に出現した「鉛筆」マークをクリック
- 「THEN」の項目の転送先にある「ゴミ箱」マークをクリックして削除
「アクションの追加」を選択し,「リダイレクト先」をクリック
「HTTPS」になっていることを確認し,ポートに
443
を入力「チェックマーク」をクリック
右上の「更新」ボタンをクリック
これで
http
でアクセスした場合もhttps
に自動変換されるようになりました。ターミナルから以下を実行してみましょう。ターミナル(ローカル側でもサーバー側でもOK)curl -I http://ドメイン名
最初に
HTTP/1.1 301 Moved Permanently
が表示され,最後にLocation: https://アプリ名:443/
が表示されていればOKです。ブラウザでも
http://ドメイン名
でアクセスしてみましょう。URLの左隣に鍵マークが付いていればOKです!お疲れ様でした!
8.9 最後に
グローバル変数の削除
作業が終わりましたので,ローカル環境で定義したグローバル変数
$APP_NAME
は消しておくこととしましょう。ローカル環境のターミナル# zsh の場合 vi ~/.zshrc # bash の場合 vi ~/.bash_profile一番最後の行にある
export APP_NAME=アプリ名
を削除して下さい。EC2のパスワード設定
次に,EC2のユーザーにパスワードを設定し,
sudo
コマンド実行時にパスワードを求められるように変更しましょう。(作業を楽にするため,EC2のユーザーはパスワード無しで
sudo
コマンドを使用できる状態にしていました)サーバー環境のターミナルsudo passwd `whoami` 設定したいEC2のパスワードを入力 EC2のパスワードを再入力【注意】「EC2のパスワード」は必ずメモしておいて下さい。
サーバー環境のターミナルsudo visudo
Vim
で開かれたら,一番最後の行のNOPASSWD:
の箇所のみ削り,次の状態にして下さい。sudoersユーザー名 ALL=(ALL) ALL【注意】
ユーザー名 ALL=(ALL) NOPASSWD: ALL
を「全て」削ってはいけません!編集を間違えると,二度と sudo コマンドを実行できなくなる恐れがありますので,慎重に行ってください。これで
sudo
コマンドを実行した際に今後はパスワードを尋ねられるようになります。以下を実行し,パスワードを求められるかどうか,パスワードを入力してコマンドを実行できるかどうかを確かめて下さい。
サーバー環境のターミナルsudo ls
9. デプロイ関連事項
この章は必要な場合のみご覧ください。
9.1 アプリ修正時の反映方法
以下のコマンドで「GitHub」の master ブランチをAWS側に反映させることができます。
ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production deploy【注意】 Heroku のデプロイで使用する
git push heroku master
は「ローカル」の master ブランチを反映させるコマンドです。bundle exec cap production deploy
コマンドは「ローカル」ではなく「GitHub」である点に注意しましょう。9.2 master以外のブランチを反映させたい
config/deploy.rbset :branch, ENV['BRANCH'] || "master"を追加すれば,例えば以下のコマンドで「GitHub」の
hoge
ブランチを反映できます。ローカル環境のターミナルbundle exec cap production deploy BRANCH=hoge例えば,現在のブランチをAWS側で動作確認したい場合は次の手順になります。
ローカル環境のターミナル# add, commit の実行後 git push origin HEAD bundle exec cap production deploy BRANCH=HEAD9.3 AWS側で Rails コマンドや rake タスクを実行する方法
サーバー側のアプリは
/var/www/$APP_NAME/current
に入っています。まずはここまで移動し,必要に応じて
yarn install --check-files
を実行して下さい。サーバー環境のターミナルcd /var/www/$APP_NAME/current yarn install --check-filesその上で,必要なコマンドを実行しましょう。コマンド例を紹介します。
- サーバー側で
rails db:seed
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails db:seed RAILS_ENV=production
bin/rails
はbundle exec rails
でも問題ありませんが,rails
ではダメです。また,RAILS_ENV=production
が必要である点に注意して下さい。
- サーバー側で
rails db:migrate:reset
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails db:migrate:reset RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1本番環境のデータベースを削除(リセットを含む)したい場合は,
DISABLE_DATABASE_ENVIRONMENT_CHECK=1
が必要です。
- サーバー側で
rails console
を実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bin/rails c -e production
オプションが
RAILS_ENV=production
ではなく-e production
の書き方になります。
- サーバー側で
rake
タスクを実行したい場合サーバー環境のターミナル(/var/www/$APP_NAME/current)bundle exec rake タスク名 RAILS_ENV=productionタスク名は
bundle exec rake -T
で確認できます。bundle exec rake
はbin/rails
でもOKですがrake
ではダメです。9.4 サーバー側で ログ を確認する方法
サーバー側の
ログ
は/var/www/$APP_NAME/shared/log
に入っています。サーバー環境のターミナルcd /var/www/$APP_NAME/shared/log lsでログファイルの一覧を確認できます。
エラーが出た場合は,
nginx.error.log
かpuma_error.log
を確認しましょう。サーバー環境のターミナル(/var/www/$APP_NAME/shared/log)# ログを全て表示したい場合 cat nginx.error.log # 最後の30行を表示したい場合 tail -n 30 nginx.error.log # ログの追加分のみを自動表示したい場合(control + c で終了) tail -f nginx.error.log10. S3
【注意】10章, 11章は,
CarrierWave
やActiveStorage
などで画像の投稿機能を実装している場合のみ,実行して下さい。現状でも画像の投稿は可能ですが,
AWS S3
を使用することで,Webサーバー(EC2
)のストレージが画像で圧迫されるのを防いだり,負荷分散ができるなど複数のメリットがあります。さらに,
CloudFront
を用いることで画像転送を高速化するところまでを解説します。10.1 S3バケットの作成
S3
は,クラウド型のオブジェクトストレージサービスです。画像に限らずいろいろなデータを保存することができ,簡単なWebサイトの公開にも使用できます。セキュリティ・耐久性共に優れ,価格も安いのが特徴です。ポートフォリオの画像投稿機能に使用する程度であれば,大抵の場合は無料利用枠内でおさまるでしょう。
S3
を利用するには,まず,バケット
を作成する必要があります。
画面左上の「サービス」を開き、検索欄に「s3」と入力し、「S3」を選択
「バケットの作成」を選択
一般的な設定
タイトル 内容 バケット名 任意 ※世界ですでに存在する名前は付けられません リージョン アジアパシフィック (東京) ap-northeast-1 【注】 バケット名とリージョン
ap-northeast-1
を忘れないようにメモしておいて下さい。
- ブロックパブリックアクセスのバケット設定
下の2つ(ACL以外)のみをチェックし,注意喚起にもチェック
「バケットを作成」をクリック
10.2 アプリ用のIAMユーザーを作成
次に,アプリ側から
S3
にアクセスするためのアクセスキー
などを入手しましょう。
画面左上の「サービス」を開き、検索欄に「iam」と入力し、「IAM」を選択
左のメニューから「ユーザー」を選択
青いボタン「ユーザーを追加」をクリック
タイトル 内容 ユーザ名 アプリ名_user アクセスの種類 「プログラムによるアクセス」にチェック
「次のステップ:アクセス権限」をクリック
「既存のポリシーを直接アタッチ」ボタンをクリック
AmazonS3FullAccess
をチェックして,「次のステップ: タグ」ボタンをクリック
- 「参考」のようにより権限を厳しくしたポリシーをアタッチするとより安全です
「次のステップ: 確認」ボタンをクリック
「ユーザーの作成」をクリック
「.csvのダウンロード」ボタンをクリック
「ユーザー名」「アクセスキーID」「シークレットアクセスキー」をメモしておいて下さい。
- 「閉じる」ボタンをクリック
参考: 権限の少ないポリシーを作成
AmazonS3FullAccess
はS3
の全ての操作ができる権限ですので,アプリに持たせる権限としては過剰すぎます。最低限必要な権限をもつポリシーを作成し,
AmazonS3FullAccess
の代わりにこちらをIAMユーザーにアタッチしておくと,万一の場合の被害を軽減することができます。IAMポリシー{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:PutObjectAcl", "s3:ListAllMyBuckets" ], "Resource": "*" } ] }さらに安全を求めるならば,バケットまで制限することも可能ですが,ここでは省略します。
10.3 CarrierWaveの設定
※ 以下,画像投稿機能に
CarrierWave
を使用していることを前提としますまず,Railsアプリに
fog-aws
をGemfile
に追加し,インストールしておきましょう。ローカル環境のターミナルbundle add fog-aws本番環境のみで
AWS S3
を使用する場合は次のように修正しましょう。(開発環境でも使用したい場合は,条件分岐せず
storage :fog
のみにして下さい)app/uploaders/image_uploader.rb# 「storage :file」を以下に置き換える if Rails.env.production? storage :fog else storage :file end次に,
S3
の「アクセスキーID」などを読み込む設定を追加しましょう。特に「シークレットアクセスキー」は,GitHubに公開してはならないので,
credentials.yml.enc
から読み込む形式とします。「リージョン」と「バケット名」は公開しても問題ありませんので,直接記載することとします。
ローカル環境のターミナルtouch config/initializers/carrier_wave.rb
(開発環境でもS3を使用したい場合は,最初の行
if Rails.env.production?
と最後の行end
を削りましょう)config/initializers/carrier_wave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: "AWS", aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), region: "ap-northeast-1" } config.fog_directory = "S3のバケット名" end end
credentials.yml.enc
を開くため,次のコマンドを実行ターミナルEDITOR=vi rails credentials:edit
- アプリが
S3
にアクセスするために必要な情報をcredentials.yml.enc
に記載しましょう
yaml
形式なので,インデント幅にはくれぐれも注意して下さい- 例えば,
access_key_id:
の後に「半角スペース1個」がないだけでエラーになりますconfig/credentials.yml.encdb: password: RDSのパスワード hostname: RDSのエンドポイント # 以下を追加 aws: access_key_id: IAMユーザーのアクセスキーID secret_access_key: IAMユーザーのシークレットアクセスキー10.4. 動作確認
念のため以下を実行し,「アクセスキーID」などが取得できることを確認しておいた方がよいでしょう。
ローカル環境のターミナルrails c # コンソール起動後 Rails.application.credentials.dig(:aws, :access_key_id) Rails.application.credentials.dig(:aws, :secret_access_key) # IAMユーザーのアクセスキーID, シークレットアクセスキーが表示されることを確認後 exitコミット・プッシュ(必要があればプルリク・マージ)などを行い,GitHub の master ブランチに変更を反映した上で,
AWS
にデプロイを行いましょう。ローカル環境のターミナルbundle exec cap production deploy
【補足】
9.2
に記載した方法で,masterブランチにマージする前に確認するのが理想的ですこれで本番環境では
S3
に画像を投稿し,読み込みができるようになりました。ブラウザから
https://ドメイン名
にアクセスし,画像を投稿してみましょう。問題なく画像が投稿・表示できていればOKです。念のため,AWSにログインし
S3
のバケットに画像が保存されているかどうかも確認しておくとよいでしょう。バケットを選択し,ディレクトリを選択していき,「オブジェクト URL」をクリックして投稿した画像が表示されていればOKです。
11. CloudFront
最後に
CloudFront
を用いて画像の表示を高速化できるようにし,さらに画像のURLを独自ドメインに変更しましょう。
CloudFront
も1年間は無料利用枠があり,料金も安いのであまり気にしなくてよいでしょう。11.1 ACM
CloudFront
で ACM 証明書を使用するには、「米国東部」リージョンで証明書をリクエストする必要があります。
AWS
の画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択【重要!】右上の「東京」を「米国東部 (バージニア北部)us-east-1」に変更
「証明書のプロビジョニング」の「今すぐ始める」ボタンをクリック
「パブリック証明書のリクエスト」を選択した状態で「証明書のリクエスト」ボタンをクリック
static.ドメイン名
を入力
static
の箇所は任意ですが,変更する場合は以降も合わせて変更して下さい
「次へ」ボタンをクリック
「DNS の検証」を選択した状態で「次へ」ボタンをクリック
タグ名 値 Name アプリ名_cloudfront
「確認」ボタンをクリック
「確定とリクエスト」ボタンをクリック
「続行」ボタンをクリック
DNS検証用の CNAME レコードを追加(8.2参照)
11.3
の作業は,状況が「検証保留中」から「発行済み」に変わってから行う必要があるため,ブラウザのタブは残しておきましょう11.2 CarrierWaveの設定
次に,Railsアプリ側のCarrierWaveの設定に追記しましょう。
config/initializers/carrier_wave.rbif Rails.env.production? CarrierWave.configure do |config| config.fog_credentials = { provider: "AWS", aws_access_key_id: Rails.application.credentials.dig(:aws, :access_key_id), aws_secret_access_key: Rails.application.credentials.dig(:aws, :secret_access_key), region: "ap-northeast-1" } config.fog_directory = "S3のバケット名" # ***** 以下を追加 ***** config.asset_host = "https://static.ドメイン名" # ***** 以上を追加 ***** end endコミット・プッシュ(必要があればプルリク・マージ)などを行い,GitHub の master ブランチに変更を反映した上で,
AWS
にデプロイを行いましょう。ローカル環境のターミナルbundle exec cap production deploy
11.3 CloudFront
【注意】
ACM
の状況が「検証保留中」から「発行済み」に変わってから行って下さい
画面左上の「サービス」を開き、検索欄に「cloudfront」と入力し、「CloudFront」を選択
「Create Distribution」ボタンをクリック
「Web」の方の「Get Started」を選択
【Origin Settings】
キー 値 Origin Domain Name S3のバケット名を選択 Restrict Bucket Access Yes 【Default Cache Behavior Settings】
キー 値 Viewer Protocol Policy Redirect HTTP to HTTPS 【Distribution Settings】
キー 値 Alternate Domain Names static.ドメイン名 SSL Certificate Custom SSL Certificate をチェックし,自分のドメインを選択 他はデフォルト設定のまま,右下の「Create Distribution」ボタンをクリック
【注意】 続きの作業は「Status」が「Deployed」になってから行ってください。
11.4 Route 53
最後に
CloudFront
用のAレコードを作成しましょう。
AWS
の画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択「ホストゾーン」をクリック
アプリで使用するドメインをクリック
「レコードを作成」ボタンをクリック
「シンプルルーティング」にチェックを入れた状態で「次へ」ボタンをクリック
「シンプルなレコードを定義」ボタンをクリック
キー 値 レコード名 static 値/トラフィックのルーティング先 CloudFront ディストリビューションへのエイリアス 米国東部 (バージニア北部) CloudFrontのドメイン名を選択 レコードタイプ A
- 「シンプルなレコードを定義」ボタンをクリック
これで全ての設定が完了です。
ブラウザから
https://ドメイン名
にアクセスし,再度画像を投稿してみましょう。問題なく画像が投稿・表示できていればOKです。念のため,AWSにログインし
S3
のバケットに画像が保存されているかどうかも確認しておくとよいでしょう。「無事全てが完了した!!」という方は是非 LGTM もお願いいたします!
12. 削除方法
AWS
は有料ですので,アプリの公開が不要となったタイミングで削除することをお勧めします。以下,削除の手順を解説しますが,特に有料となっている以下の削除を忘れないようにしましょう。
- RDSインスタンス【高額!】
- ALB(ロードバランサ)【高額!】
- EC2インスタンス【高額!】
- Elastic IP(EC2を削除すると課金対象)
- Route 53
- ACM
- S3(画像投稿機能を付けた場合)
- CloudFront(画像投稿機能を付けた場合)
12.1 Route 53 の削除
Route 53 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「route」と入力し、「Route 53」を選択)
画面左のメニューバーの「ホストゾーン」をクリック
アプリで使用したドメインをクリック
タイプが
A
とCNAME
のものにチェックを入れ,「削除」ボタンをクリックし,さらに「削除」ボタンをクリック右上の「削除」ボタンをクリック
「削除」と入力し,「削除」ボタンをクリック
12.2 ALB の削除
EC2 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択)
画面左のメニューバーの「ロードバランサー」をクリック
「アクション」ボタンをクリックし,「削除」をクリック
- 使用しているロードバランサーが表示されない場合は,右上のリージョンが「東京」になっているか確認
「削除」をクリック
12.3 CloudFront の削除
【備考】画像投稿機能を付けていない場合は,次に進んで下さい。
CloudFront ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「cloudfr」と入力し、「CloudFront」を選択)
使用している
Distribution
にチェックを入れて,「Disable」ボタンをクリック「Yes, Disabled」ボタンをクリック
「Status」が「Disabled」になるまで待ちましょう
使用している
Distribution
にチェックを入れて,「Delete」ボタンをクリック「Yes, delete」ボタンをクリック
「Close」ボタンをクリック
12.4 SSL証明書 の削除
Certificate Manager ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「acm」と入力し、「Certificate Manager」を選択)
アプリで使用したドメインを選択し,「アクション」ボタンをクリックし,「削除」をクリック
「削除」ボタンをクリック
【備考】画像投稿機能を付けている場合は,「東京」リージョンだけでなく「バージニア北部」リージョンのACMも削除して下さい。
12.5 EC2 の削除
- EC2 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「ec2」と入力し、「EC2」を選択)
ターゲットグループの削除
画面左のメニューバーの「ターゲットグループ」をクリック
アプリで使用していたものを選択した状態で「Action」のプルダウンの「Delete」をクリック
「Yes, delete」ボタンをクリック
EC2 インスタンスの削除
- 画面左のメニューバーの 「インスタンス」をクリック
- 削除したいインスタンスを選択した状態で「アクション」ボタンをクリックし,「インスタンスの状態」「インスタンスを終了」をクリック(「停止」ではない)
- 「終了」ボタンをクリック
Elastic IP の解放
- 画面左のメニューバーの
Elastic IP
をクリック- 削除したい
Elastic IP
を選択した状態で「アクション」ボタンをクリックし,「Elastic IPアドレスの解放」をクリック
- EC2終了後少し待たないと解放できません
- 削除したい
Elastic IP
が消えたことを確認その他
- 「キーペア」も削除しましょう
- 「セキュリティグループ」は
VPC
削除時に自動的に削除されます12.6 RDS の削除
- RDS ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「rds」と入力し、「RDS」を選択)
s RDS インスタンスの削除
- 画面左のメニューバーの「データベース」をクリック
- 削除したい DB を選択し,「アクション」ボタンをクリックし,「削除」をクリック
- 「最終スナップショットを作成しますか?」のチェックを外し,「インスタンスの削除後、システムスナップショットとポイントインタイムの復元を含む自動バックアップが利用不可となることを了承しました。」にチェックを入れ,フィールドに「delete me」を入力して「削除」ボタンをクリック
その他
- 「サブネットグループ」を削除
- RDSが削除されるまで削除できません
- 「パラメータグループ」は残してよいでしょう。
12.7 VPC の削除
VPC ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「vpc」と入力し、「VPC」を選択)
削除したい VPC を選択し,「アクション」ボタンをクリックし,「VPC を削除」をクリック
フィールドに「削除」と記入して「削除」ボタンをクリック
サブネット,インターネットゲートウェイ,ルートテーブルも同時に削除されます。
12.8 S3/IAM の削除
【備考】画像投稿機能を付けていない場合は,次に進んで下さい。
S3 の削除
S3 ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「s3」と入力し、「S3」を選択)
アプリで使用したバケットを選択し,「空にする」ボタンをクリック
「完全に削除」と入力し「空にする」ボタンをクリック
「終了」ボタンをクリック
「削除」ボタンをクリック
「バケット名」を入力し,「バケットを削除」ボタンをクリック
IAM の削除
IAM ダッシュボードに移動
- (画面左上の「サービス」を開き、検索欄に「iam」と入力し、「IAM」を選択)
画面左のメニューバーの「ユーザー」をクリック
「アプリ名_user」にチェックを入れ,「ユーザーの削除」ボタンをクリック
- アプリと関係ないものを削除しないように注意!
「はい,削除します」ボタンをクリック
12.9 キーペアの削除
GitHub の公開鍵を削除
- ブラウザでGitHubにアクセス
- 右上のサムネイル画像をクリック
- 「Settings」をクリック
- 左メニューバーから「SSH and GPG keys」をクリック
- 「アプリ名_git_rsa/pub」の箇所で「Delete」ボタンをクリック
- 「I understand, please delete this SSH key」ボタンをクリック
ローカル環境のキーペアの削除
最後に,ローカル環境の秘密鍵と設定を削除しておきましょう。
ローカル環境のターミナルcd ~/.ssh rm -f アプリ名.pem vi config # Host アプリ名 の設定を削除
- 投稿日:2020-11-26T18:00:43+09:00
サルでもできる!? Rails6アプリをAWS EC2にデプロイするまでの全手順【前半】(VPC, RDS, EC2, Capistrano)
この記事では,画像投稿機能の付いた
Rails 6
のアプリをAWS EC2
にデプロイするまでの全過程を解説します。Railsアプリのデプロイに関する記事はたくさん見かけますが,初学者にとっては
「具体的に何をすればよいかが分からない」
記事がほとんどで,ましてや「独自ドメインの設定方法」や「投稿画像を独自ドメインでCloudFrontから配信する方法」まで網羅的に解説を行っている記事は見当たらない状態です。
そこで,「Rails初学者が初めてAWSにデプロイする際に本当に参考となる記事」を目指して書かせていただきました。
「
Heroku
にデプロイしたことはあるけれど,AWS
にデプロイしたことがない」という方を対象としますので,AWS
の操作は,直感的に操作できるAWS マネジメントコンソール
で行います。
AWS CLI
やTerraform
などのツールは使用しませんので,あらかじめご了承下さい。
章 タイトル 【前半】 <-- こちら 1章 はじめに 2章 VPC 3章 RDS 4章 EC2 5章 サーバー構築 6章 デプロイ(Capistrano) 【後半】 7章 独自ドメイン 8章 HTTPS化(ACM, ALB) 9章 デプロイ関連事項 10章 S3 11章 CloudFront 12章 削除方法 1. はじめに
1.1 注意事項
この記事における注意事項を列記します。
料金
AWS
は有料のサービスで,いわゆる従量課金制です(サービスの使用量に応じて料金が決まります)。この記事の構成で
AWS
を利用した場合,ポートフォリオのようにあまりアクセスが来ないアプリであっても,(無料利用枠を使用する前提で)月におよそ3000円前後かかります。
RDS
,ALB
などを使用せず,EC2
にデータベースシステムをインストールする構成にすればもっと安く済ませることができますが,ポートフォリオのアピール材料としては弱くなるでしょう。なお,エラーが発生した際に原因を特定しやすくするため,
AWS
へのデプロイはアプリの完成後ではなく
,開発初期の段階
から行うことをお勧めします。ただ,料金の問題がありますので,アプリの開発初期は
Heroku
にデプロイし,仕上げの段階でAWS
にデプロイするという手法もありでしょう。Railsアプリの条件
AWSにデプロイ予定のアプリが,以下の条件を満たすことを前提とします。
アプリの Rails のバージョンが
6
であること(5
でも多分OK)データベースは
MySQL 5.7
もしくはPostgreSQL
を使用画像投稿機能がある場合は
CarrierWave
を使用
6.1
に画像投稿機能の付いたサンプルアプリを作成する方法を紹介しておりますので,必要がございましたらご利用下さい。構成図
以下のような一般的な構成を目指します。(料金の都合上,冗長化は行いません)
サーバー環境
- 【Web サーバー】 Nginx
- 【アプリケーションサーバー】 Puma
使用する AWS のサービス
- VPC(Amazon Virtual Private Cloud)
- RDS(Amazon Relational Database Service)
- EC2(Amazon Elastic Compute Cloud)
- Route 53
- ACM(Certificate Manager)
- ALB(Application Load Balancer)
- S3(Amazon Simple Storage Service)
- IAM(AWS Identity and Access Management)
- CloudFront
基礎知識の解説
この記事は,「画像投稿機能の付いた Rails アプリを AWS EC2 にデプロイし,独自ドメインでアクセスできるようにする」ことを主目的としております。
最低限度知っておくべき内容は触れますが,インフラの基礎知識は解説しません。
AWS に必要な基礎知識を学べる本はたくさんありますし,Udemyにも丁寧な解説動画が存在します。デプロイの完了後でもよいですので,是非学習されることをお勧めします。
注意点
理解が不十分な状態で進められる場合は,
絶対にミスをしない
ように気を付けて下さい。1つのミスで最初からやり直すことになり,数時間の作業が無駄になる可能性があります。コメントについて
記事内の改善点・間違いなどございましたら,遠慮なくご指摘下さい。可能な限りで記事にも反映させていただきます。
Qiita上の質問には原則お答えする時間が取れませんので,あらかじめ了解いただいた上でご質問下さい。
メモ
作業中にパスワードなど各自設定が異なる部分が複数存在します。メモ帳に以下を貼り付け,決まり次第埋めていくようにされるとよいでしょう。
メモ【アプリ名】 【RDS】 ●マスターユーザー名 ●マスターパスワード ●エンドポイント 【EC2】 ●Elastic IP ●sshでサインインするときのコマンド ssh アプリ名 ●ユーザー名 ●パスワード 【ドメイン】 ●ドメイン名 ●ネームサーバー情報 【S3】 ●バケット名 ●リージョン 【IAM】 ●ユーザー名 ●アクセスキーID ●シークレットアクセスキー 【CloudFront】 static.ドメイン名まずは,AWSで使用する
アプリ名
を決め,上記にメモして下さい。ただし,「aws_sample_app」のようにスネークケース
表記であることを前提とします。(アルファベット大文字は使わないで下さい)「(AWSで使用する)アプリ名」は,「Railsのアプリ名」「GitHubのリポジトリ名」と合わせる方が混乱しづらいと思いますが,同じでなくても問題ありません。
以下,
アプリ名
と記載している箇所は,全てこのメモ通りにして下さい。1.2 AWSアカウントの作成・初期設定
要点のみ記載します。
AWSアカウントの作成
- https://portal.aws.amazon.com/billing/signup
- メールアドレス・パスワードは超重要です。絶対に忘れないようにし,また他人に知られないように注意しましょう。不正利用されると高額の料金を請求される可能性があります。
- パスワードは,大文字・小文字・数字・記号を含む16文字以上の強固なものを設定しましょう。
- サポートプランは特に用事がなければ「ベーシックプラン」でOK
「セキュリティステータス」に全てチェックが入るように設定を進めましょう。
【お勧め参考記事】 https://qiita.com/tmknom/items/303db2d1d928db720888
- ルートアカウントの MFA を有効化
- セキュリティ向上のため2段階認証を導入
- 個々の IAM ユーザーの作成
- 最初に発行される「ルートアカウント」は,セキュリティの都合上,今後サインインに使用しないようにします
- 普段のサインインに使用する
IAM
ユーザーを作成- 「パスワードのリセットが必要」は不要なのでチェックを外しましょう
- 今後のサインインに必要となる「アカウントID」「ユーザー名」「パスワード」を忘れないようにしましょう
- グループを使用してアクセス許可を割り当て
- ほぼ全ての権限を持つ「AdministratorAccess」のポリシーを持つグループを作成し,作成した
IAM
ユーザーを追加- IAMパスワードポリシーの適用
最後に「請求アラーム」を作成し,課金状況を確認できるようにしておくことをお勧めします。
【お勧め参考記事】 https://www.kakiyoro.com/archives/2198
2. VPC
Amazon VPC
とはAmazon Virtual Private Cloud
の略称で,ユーザー専用のプライベートなネットワーク空間を構築できるサービスです。RailsアプリをAWSで動作させるために,Webサーバーを配置する
EC2
とデータベースシステムを動かすRDS
を使用しますが,これらを配置するには先にVPC
を設定する必要があります。
Amazon VPC
は追加料金なしで使用できます。(参考:https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/what-is-amazon-vpc.html)2.1 VPC の作成
2章では以下の部分を作成していきます。
【注意】 メニューバー右側の真ん中に「米国」などと表示されている場合は,「東京(アジアパシフィック(東京) ap-northeast-1)」に変更して下さい
- 画面左上の「サービス」を開き、検索欄に「VPC」と入力し、「VPC」を選択
【注意】 以下,左上の「New VPC Experience」をONにしていることを前提とします。
- 画面左のメニューバー(もしくは,ダッシュボード内の)の「VPC」をクリック
- 「VPCを作成」ボタンをクリック
キー 値 名前タグ アプリ名_vpc IPv4 CIDR ブロック 10.0.0.0/16 【注意】1章で注意しましたとおり,「アプリ名」の箇所はあらかじめ
メモ
しておいた「アプリ名」を使用して下さい
- 他はデフォルトのままで「VPCを作成」ボタンをクリック
2.2 サブネット の作成
VPCの中に,「インターネットから直接通信できる
EC2用
のサブネット」と「インターネットから直接通信できないRDS用
のサブネット」を2つずつ作成していきましょう。(許可する接続方法は後に設定します)
- 画面左のメニューバーから「サブネット」を選択
EC2 用のサブネット
HTTPS化
する際にALB
を使用するため,異なるアベイラビリティーゾーン
に属するサブネットを2つ
用意する必要があります。
- 「サブネットの作成」ボタンをクリック
キー 値 VPC アプリ名_vpc ※リストから選択
キー 値 名前タグ アプリ名_public_1a_subnet アベイラビリティーゾーン ap-northeast-1a ※リストから選択 IPv4 CIDR ブロック 10.0.0.0/24
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_public_1c_subnet アベイラビリティーゾーン ap-northeast-1c ※リストから選択 IPv4 CIDR ブロック 10.0.1.0/24 ※ まだ作成しますので,「サブネットを作成」ボタンをクリックしないこと!
RDS 用のサブネット
RDS
を利用するには異なるアベイラビリティーゾーン
に属するサブネットを2つ
用意する必要があります。
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_private_1a_subnet アベイラビリティーゾーン ap-northeast-1a IPv4 CIDR ブロック 10.0.10.0/24
- 「新しいサブネットを追加」ボタンをクリック
キー 値 名前タグ アプリ名_private_1c_subnet アベイラビリティーゾーン ap-northeast-1c IPv4 CIDR ブロック 10.0.11.0/24
「サブネットを作成」ボタンをクリック
下図の状態になっていることを確認しておきましょう
2.3 インターネットゲートウェイ の作成
VPC
内からインターネット
に接続するための「出入口」に相当するインターネットゲートウェイ
を作成しましょう。
- 画面左のメニューバーから「インターネットゲートウェイ」を選択
- 「インターネットゲートウェイの作成」ボタンをクリック
キー 値 名前タグ アプリ名_gateway
- 他はデフォルトのままで「インターネットゲートウェイの作成」ボタンをクリック
- フラッシュで表示されている「VPCへアタッチ」をクリック
- (「アクション」を選択し、「VPCにアタッチ」を選択してもOK)
キー 値 使用可能なVPC アプリ名_vpc
- 「インターネットゲートウェイのアタッチ」ボタンをクリック
2.4 ルートテーブル の作成
インターネットゲートウェイ
をアタッチしただけでは,サブネットからインターネットにアクセスすることはできません。
インターネットゲートウェイ
へ転送する経路であるルートテーブル
を設定する必要があります。
- 画面左のメニューバーから「ルートテーブル」を選択
- 「ルートテーブルの作成」ボタンをクリック
キー 値 名前タグ アプリ名_table VPC アプリ名_vpc
- 「作成」ボタンをクリック
「閉じる」ボタンをクリック
作成したルートテーブルを選択し,「アクション」ボタンをクリックし,「ルートの編集」を選択
- 「ルートの追加」ボタンをクリック
local
を消さないこと!
キー 値 送信先 0.0.0.0/0 ターゲット 「Internet Gateway」を選択し,先ほど作成した「アプリ名_gateway」を選択
- 「ルートの保存」をクリック
「閉じる」ボタンをクリック
(作成したルートテーブルを選択したまま)「アクション」ボタンをクリックし,「サブネットの関連付けの編集」を選択
「アプリ名_public_1a_subnet」「アプリ名_public_1c_subnet」のみを選択し,「保存」ボタンをクリック
2.5 セキュリティグループ の作成
インスタンスごとに許可する通信を設定するため,
セキュリティグループ
を作成しておきましょう。(
EC2
やRDS
に適用する作業は,後で行います)EC2 用のセキュリティグループ
【構成内容】 クライアント --(HTTP or SSH)-->
EC2
- 画面左のメニューバーの「セキュリティグループ」を選択
- 「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_ec2_security_group 説明 アプリ名_ec2_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」を2回クリック
キー 値 タイプ HTTP ※「HTTPS」ではありません! プロトコル TCP ※自動選択 ポート範囲 80 ※自動選択 ソース 任意の場所 (0.0.0.0/0 と ::/0 が表示) 説明 ※空白でOK
キー 値 タイプ SSH プロトコル TCP ※自動選択 ポート範囲 22 ※自動選択 ソース マイIP (自分のグローバルIPが表示) 説明 ※空白でOK 【注意】ソースを
マイIP
とすることで,SSH接続できるIPアドレスを制限できます。ただし,自宅以外でEC2
にアクセスする可能性がある場合は,他のIPアドレスも登録が必要です。(意味が分からない場合は,SSH
のソースも任意の場所
に設定して下さい)RDS 用のセキュリティグループ
【構成内容】
EC2
--(TCP)-->RDS
データベースは
EC2
からのリクエストのみを受け付けるように設定しておきます。画面左のメニューバーの「セキュリティグループ」を選択し,「セキュリティグループを作成」ボタンをクリック
キー 値 セキュリティグループ名 アプリ名_db_security_group 説明 アプリ名_db_security_group VPC アプリ名_vpc 「インバウンドルール」の「ルールを追加」をクリック
【注意】アプリで使用するデータベースシステムを確認し,「いずれか一方」のルールを追加して下さい
MySQL
の場合
キー 値 タイプ MySQL/Aurora プロトコル TCP ※自動選択 ポート範囲 3306 ※自動選択 ソース カスタム : アプリ名_ec2_security_group 説明 ※空白でOK 「セキュリティグループを作成」をクリック
PostgreSQL
の場合
キー 値 タイプ PostgreSQL プロトコル TCP ※自動選択 ポート範囲 5432 ※自動選択 ソース カスタム : アプリ名_ec2_security_group 説明 ※空白でOK 「セキュリティグループを作成」をクリック
3. RDS
Amazon RDS
とはAmazon Relational Database Service
の略称で,MySQL
やPostgreSQL
のようなデータベース管理システム(DBMS
)を最適な動作条件で利用できるサービスです。
RDS
は運用負荷が低く非常に便利なのですが,コストが高い
ため注意が必要です。AWSアカウント作成後,1年間は一定の条件で無料となりますが,不要になった時点で削除することをお勧めします。
3.1. サブネットグループの作成
2.2
で作成したRDS
用のサブネット2つをグループ化しましょう。
画面左上の「サービス」を開き、検索欄に「RDS」と入力し、「RDS」を選択
画面左のメニューバーの「サブネットグループ」を選択し,右上の「DB サブネットグループを作成」ボタンをクリック
サブネットグループの詳細
キー 値 名前 アプリ名_subnet_group_db 説明 アプリ名_subnet_group_db VPC アプリ名_vpc
- サブネットの追加
- 異なる
アベイラビリティーゾーン
に属するサブネットを2つ以上選択する必要がありますマルチ AZ
構成時に必要となるため,今回のようにマルチ AZ
を使用しない場合にも必須となります
キー 値 アベイラビリティーゾーン ap-northeast-1a, ap-northeast-1c サブネット 10.0.10.0/24, 10.0.11.0/24 の2つを選択 「作成」ボタンをチェック
3.2 パラメータグループの作成(MySQL限定)
【注意】
PostgreSQL
の場合はスキップして下さい
RDS
のMySQL
のデフォルト文字コードはlatin1
であり,日本語に対応していません。文字コードを変更するためのパラメータグループを先に作成しておきましょう。
(1度作成すれば使い回しが可能です)
- 画面左のメニューバーの「パラメータグループ」を選択
「パラメータグループの作成」ボタンをクリック
- パラメータグループの詳細
キー 値 パラメータグループファミリー mysql5.7 グループ名 mysql57-supported-in-ja 説明 parameter group for mysql5.7 supported in ja
作成した「mysql57-supported-in-ja」をクリック
「パラメータの編集」ボタンをクリック
検索窓にキーをコピペして値を変更
キー 値 character_set_client utf8 character_set_connection utf8 character_set_database utf8mb4 character_set_results utf8 character_set_server utf8mb4 skip-character-set-client-handshake 1
- 「変更の保存」ボタンをクリック
3.3 DBインスタンスの作成
画面左のメニューバーの「データベース」を選択
「データベースを作成」ボタンをクリック
「MySQL」の場合と「PostgreSQL」の場合で設定が異なりますので,いずれか片方を実行して下さい。
3.3.1 MySQLの場合
- データベース作成方法を選択
「標準作成」を選択
- エンジンのオプション
キー 値 エンジンのタイプ MySQL バージョン MySQL 5.7.* (*の箇所は最新のものを推奨)
- テンプレート
「無料利用枠」を選択
- 設定
【注意】ここの「アプリ名」の
_
は ハイフン-
とすること
【注意】マスターユーザー名・パスワードをメモしておくこと
キー 値 DB インスタンス識別子 アプリ名-db マスターユーザー名 root マスターパスワード 任意
- DB インスタンスサイズ
db.t2.micro(デフォルト)
- ストレージ
※デフォルト設定で
- 可用性と耐久性
※デフォルト設定で
- 接続
「アプリ名_vpc」を選択
- 「追加の接続設定」のドロップダウンをクリック
キー 値 サブネットグループ アプリ名_subnet_group_db ※2.1で作成 セキュリティグループ アプリ名_db_security_group ※1.5で作成, default は外す アベイラビリティーゾーン ap-northeast-1a
- データベース認証
※デフォルト設定で
「追加設定」をクリック
データベースの選択肢
キー 値 最初のデータベース名 アプリ名_production DB パラメータグループ mysql57-supported-in-ja オプショングループ ※デフォルト設定
- バッグアップ以降
※デフォルト設定で
- 「データベースの作成」ボタンをクリック
3.3.2 PostgreSQLの場合
まず,ターミナルでローカルで使用している
PostgreSQL
のバージョンを確認しておきましょう。psql -V
- データベース作成方法を選択
「標準作成」を選択
- エンジンのオプション
PostgreSQL
のバージョンは,上記で確認したローカルのバージョンに合わせた方が無難です。メジャーバージョンを合わせれば十分なので,例えばローカルが
12.3
ならば,12.* (*の箇所は最新のもの) をお勧めします。2020年11月時点ではバージョンが
13
に対応していないので,ローカルのバージョン13
の場合は最新のバージョンでよいでしょう。
キー 値 エンジンのタイプ PostgreSQL バージョン ※上記を参考に設定
- テンプレート
「無料利用枠」を選択
- 設定
【注意】ここの「アプリ名」の
_
は ハイフン-
とすること
【注意】マスターユーザー名・パスワードをメモしておくこと
キー 値 DB インスタンス識別子 アプリ名-db マスターユーザー名 postgres マスターパスワード 任意
- DB インスタンスサイズ
db.t2.micro(デフォルト)
- ストレージ
※デフォルト設定で
- 可用性と耐久性
※デフォルト設定で
- 接続
「アプリ名_vpc」を選択
- 「追加の接続設定」のドロップダウンをクリック
キー 値 サブネットグループ アプリ名_subnet_group_db ※2.1で作成 セキュリティグループ アプリ名_db_security_group ※1.5で作成, default は外す アベイラビリティーゾーン ap-northeast-1a
- データベース認証
※デフォルト設定で
「追加設定」をクリック
データベースの選択肢
キー 値 最初のデータベース名 アプリ名_production DB パラメータグループ ※デフォルト設定 オプショングループ ※デフォルト設定
- バッグアップ以降
※デフォルト設定で
- 「データベースの作成」ボタンをクリック
3.4 エンドポイントの確認
アプリ名を選択
「接続とセキュリティ」の「エンドポイント」をメモ
- データベースが作成されるまで待つ必要がありますので,別タブで次の
EC2
の設定に進めるとよいでしょう4. EC2
Amazon EC2
とはAmazon Elastic Compute Cloud
の略称で,コンピューティング性能をクラウド内で提供するサービスです。サーバーに必要なものをクラウド内で借りることができます。Railsのアプリをこの
EC2
にデプロイし,ブラウザからアクセスできるように準備を行います。EC2 も運用に料金がかかりますので,不要になったインスタンスなどは削除するようにしましょう。
4.1 インスタンスの作成
画面左上の「サービス」を開き、検索欄に「EC2」と入力し、「EC2」を選択
画面左のメニューバーの「インスタンス」を選択し,「インスタンスを起動」ボタンをクリック
ステップ 1: Amazon マシンイメージ (AMI)
「無料利用枠の対象」タグの付いた「Amazon Linux 2 AMI (HVM), SSD Volume Type」「64ビット (x86)」の「選択」ボタンをクリック
ステップ 2: インスタンスタイプの選択
- 「無料利用枠の対象」タグの付いた「t2.micro」が選択されていることを確認した上で,「次のステップ」ボタンをクリック
- 「確認と作成」ボタンをクリックしないこと。クリックした場合は,「戻る」ボタンをクリックしてステップ3まで移動しましょう
ステップ 3: インスタンスの詳細の設定
キー 値 ネットワーク アプリ名_vpc サブネット アプリ名_public_1a_subnet 他はデフォルト設定のまま「次のステップ」ボタンをクリック
ステップ 4: ストレージの追加
「次のステップ」ボタンをクリック
ステップ 5: タグの追加
「タグの追加」ボタンをクリック
キー 値 Name 「アプリ名_instance」を選択 「次のステップ」ボタンをクリック
ステップ 6: セキュリティグループの設定
「既存のセキュリティグループを選択する」にチェック
「アプリ名_ec2_security_group」にチェック
「確認と作成」ボタンをクリック
ステップ 7: インスタンス作成の確認
- セキュリティグループの「名前」が「アプリ名_ec2_security_group」になっていることを確認した上で,「起動」ボタンをクリック
既存のキーペアを選択するか、新しいキーペアを作成します。
「新しいキーペアの作成」を選択
「キーペア名」は「アプリ名」を入力
メモ
しているアプリ名と全く同じにして下さい(ハイフン-
を使用せず,アンダースコア_
を使用)「キーペアのダウンロード」を選択
アプリ名.pem
をダウンロードできます。後にEC2
のログインで利用します「インスタンスの作成」ボタンをクリック
作成ステータス
「インスタンスの表示」ボタンをクリック
4.2 Elastic IPの作成、紐付け
インターネットに接続するには
グローバルIPアドレス
が必須です。現状ではこの
グローバルIPアドレス
は固定化されておらずEC2インスタンス
を再起動した際に変更されてしまいます。(URLが変化してしまう!)
Elastic IP
設定することで,グローバルIPアドレス
を固定化することができます。
Elastic IP
はこれから行うEC2インスタンス
との関連付けを行っている状態では無料ですが,関連付けたEC2インスタンス
を削除したり停止させると料金が発生するようになります。
EC2インスタンス
を削除する際はElastic IP
の開放を忘れないように注意しましょう。Elastic IPの作成
画面左のメニューバーの「Elastic IP」を選択
「Elastic IP アドレスの割り当て」ボタンをクリック
「割り当て」ボタンをクリック
Elastic IPの紐付け
- 先ほど割り当てた
Elastic IP
を選択した状態で、「アクション」ドロップダウンを選択し、「Elastic IP アドレスの関連付け」をクリックここで,表示されている
Elastic IP
は必ずメモしておいて下さい。
キー 値 インスタンス アプリ名_instance プライベート IP アドレス ※クリックして表示されるIPを選択 再関連付け チェックを入れる
- 「関連付ける」ボタンをクリック
4.3 EC2へのログイン
アプリ名を定義(ローカル環境)
作業ミスを減らすため,ターミナルで頻出する
アプリ名
を一時的にグローバル変数として定義しておきましょう。
アプリ名
の箇所は,各自がメモしているものに置き換えて実行して下さい。ターミナルAPP_NAME=アプリ名 echo $APP_NAME(例)APP_NAME=aws_sample_app echo $APP_NAME最後のコマンドで,「アプリ名」が正しく表示されていることを確認した上で,以下を実行して下さい。
【補足】間違った場合は再度上記を実行し直してから進めて下さい。また,コマンドは原則コピペして下さい。1文字間違っただけで大きく時間をロスする可能性があります。
ターミナル# zsh の場合 echo "export APP_NAME=$APP_NAME" >> ~/.zshrc source ~/.zshrc # bash の場合 echo "export APP_NAME=$APP_NAME" >> ~/.bash_profile source ~/.bash_profile【備考】 使用しているシェルスクリプトが
zsh
かbash
か分からない場合はecho $SHELL
を実行して確認して下さいキーペアの移動・アクセス権の付与
【参考】 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-key-pairs.html
4.1 でダウンロードしたキーペア
アプリ名.pem
は.ssh
ディレクトリに移動し,利用できる状態にしておきましょう。ターミナルcd mkdir .ssh mv Downloads/$APP_NAME.pem .ssh chmod 400 .ssh/$APP_NAME.pem ls -l .ssh/$APP_NAME.pem最後のコマンドで
-r-------- (略) .ssh/アプリ名.pem
が表示されていればOKです。【補足】
mv
コマンド実行時にNo such file or directory
が表示された場合は,Google Chrome の下に現れているアプリ名.pem
のドロップダウンメニューから,キーペアの場所を確認して,直接,ホームディレクトリの.ssh
ディレクトリに移動させて下さい。キーペアのファイル名がアプリ名.pem
になっているかどうかも確認しましょう。EC2 インスタンスの状態を確認
EC2
の画面左のメニューバーの「インスタンス」をクリックし,作成した EC2インスタンスの「インスタンスの状態」が実行中
となっているか確認して下さい
実行中
になっていない場合はしばらく待ってからブラウザをリロードして下さい【補足】4.2で
Elastic IP
をメモし忘れた人は,作成した EC2インスタンス を選択し,Elastic IP
をメモして下さいssh接続の設定ファイルを作成
EC2インタスタンス
にログインするには,「ホスト名」「ユーザー名」「AWSからダウンロードしたキーペア(秘密鍵)」が必要になります。これらをログインの度に毎回記述するのは面倒なので,設定ファイルに記載し,使える状態にしましょう。
ローカル環境のターミナルvi ~/.ssh/config
Vim
エディタでファイルが開かれますので,以下を記述して下さい。(デフォルトでec2-user
という名前のユーザーが用意されています)ローカル環境のターミナル(~/.ssh/config)Host アプリ名 Hostname ElasticIPを記入 User ec2-user IdentityFile ~/.ssh/アプリ名.pem【参考】 「アプリ名」が
aws_sample_app
, 「Elastic IP」が172.217.161.46
の場合は,次の形式となります。(例)Host aws_sample_app Hostname 172.217.161.46 User ec2-user IdentityFile ~/.ssh/aws_sample_app.pem【補足】 Vimの基本
一般のテキストエディタは,ファイルを開いてすぐに文字が入力できます。
Vim
はインサートモード
に変更しなければキー入力ができません。ここは初学者が非常に混乱しやすいところですので,くれぐれもご注意下さい。
以下は最低限覚えておきましょう。
Vim
の起動時は「ノーマルモード」- 文字をキー入力したいときは
i
を入力し,「インサートモード」に変更する必要がある
- 「かな」入力モードでは
i
を入力しても効果が出ないので,「英数」入力モードに切り替えてから行うこと- 「ノーマルモード」への移行は,
esc
- 保存終了は「ノーマルモード」にしてから
:wq
- (保存せずに)強制終了は「ノーマルモード」にしてから
:q!
EC2にログイン
それでは,
EC2インタスタンス
にログインしてみましょう。ターミナルssh アプリ名
Are you sure you want to continue connecting (yes/no/[fingerprint])
と表示されたら,yes
と入力してEnterキーを押しましょう。これで,
EC2インタスタンス
にログインできます。
【備考】ここでSSH接続できない場合は,以下の可能性があります。
先ほど作成した
~/.ssh/config
にミスがある4.3で,キーペアが指定箇所に移動できていない or パーミッションを適切に変更できていない(
ls -l ~/.ssh/$APP_NAME.pem
で確認)
Elastic IP
をメモし間違えている2.5で作成した「EC2 用のセキュリティグループ(アプリ名_ec2_security_group)」の設定を間違えている
- SSHのソースが
マイIP
の場合は,IPアドレスが変わっていないかも確認しましょう(不明な場合は任意の場所
に変更)4.1で設定したEC2 用のセキュリティグループが「アプリ名_ec2_security_group」になっていない
2.4で作成したルートテーブルの「サブネットの関連付け」を間違えている
4.4 EC2の初期設定
(参考)Amazon Linux インスタンスでユーザーアカウントを管理する
要注意
今後,EC2にログインした状態の
サーバー環境のターミナル
と,通常のローカル環境のターミナル
のどちらで操作するかを「必ず」確認して下さい。1度でも間違えると,エラー解決に大きく時間を取られる可能性があります。なお,一定時間が経過しますと,EC2からログアウトしますので,その点にも注意しましょう。
新規ユーザーアカウントの作成
今後
EC2
での作業やCapistrano
で利用するユーザーを作成しましょう。作業を楽にするため,しばらくパスワード無しで sudo コマンドを使える状態にしておきます。EC2にログインした状態の
サーバー環境のターミナル
で以下を実行しましょう。「ユーザー名」の箇所は自由に決め,
メモ
しておいて下さい。サーバー環境のターミナルAPP_USER=ユーザー名 echo $APP_USER最後のコマンドで,「ユーザー名」が正しく表示されていることを確認した上で,以下を実行して下さい。
サーバー環境のターミナルsudo adduser $APP_USER echo "$APP_USER ALL=(ALL) NOPASSWD: ALL" | sudo EDITOR='tee -a' visudo > /dev/null sudo su - $APP_USER sudo ls最初の表示が
ec2-user
から「自分の決めたユーザー名」に変更され,最後のコマンドでパスワードを求められなければOKです。【補足】2番目の操作は
sudo visudo
実行後,一番最後の行にユーザー名 ALL=(ALL) NOPASSWD: ALL
を追加する操作ですアプリ名を定義(サーバー環境)
作業ミスを減らすため,サーバー環境でも「アプリ名」をグローバル変数として定義しておきましょう。
サーバー環境のターミナルAPP_NAME=アプリ名 echo $APP_NAME最後のコマンドで,「アプリ名」が正しく表示されていることを確認した上で,以下を実行して下さい。
(間違っている場合は再度上記を実行し直してから進めて下さい)
サーバー環境のターミナルecho "export APP_NAME=$APP_NAME" >> ~/.bash_profile source ~/.bash_profile新規ユーザーでssh接続するための設定
新規ユーザーでssh接続できるようにするには,
アプリ名.pem
(秘密鍵)に対応する公開鍵
をEC2
の~/.ssh/authorized_keys
に配置し,適切な権限を与えておく必要があります。サーバー環境のターミナルmkdir .ssh -m 700 vi .ssh/authorized_keysサーバー側でVimエディタが開かれます。
ここで,新しく
ローカル
環境のターミナルを用意して下さい。(command + n
もしくはcommand + t
)そして,
ローカル
環境のターミナルで秘密鍵(アプリ名.pem)
から公開鍵
をコピーして下さい。ローカル環境のターミナルssh-keygen -y -f ~/.ssh/$APP_NAME.pem | pbcopy(コマンドを実行するだけでコピーされますので,
command + c
は不要です。もしpbcopy: command not found
が表示される場合は| pbcopy
を削って実行し,直接コピーして下さい)その後,サーバー環境のターミナルに戻って以下の操作を行ってください。
サーバー環境のターミナル# 公開鍵を貼り付け,保存終了 chmod 600 .ssh/authorized_keys exit exitこれで,新しく作成したユーザーでもログインができるようになりました。
ログイン時のユーザー名を変更しましょう。
ローカル環境のターミナルvi ~/.ssh/config
- 「ユーザー名」を
ec2-user
からメモしたユーザー名
に変更しましょう。ローカル環境のターミナル(~/.ssh/config)Host アプリ名 Hostname ElasticIP User ユーザー名 ★ここを変更★ IdentityFile ~/.ssh/アプリ名.pem
yml:(ユーザー名が take の場合)
Host aws_sample_app
Hostname 172.217.161.46
User take
IdentityFile ~/.ssh/aws_sample_app.pem
4.5 今後のEC2のログイン方法
再度,以下のコマンドで
EC2インスタンス
にログインしてみましょう。ローカル環境のターミナルssh アプリ名
ec2-user
ではなく各自が決めたユーザー名でログインできるはずです。デフォルトユーザーは必要なくなりましたので,削除しておきましょう。
サーバー環境のターミナルsudo userdel -r ec2-user5. サーバー構築
Railsアプリを実行できるようにするための環境構築を行っていきます。
EC2インスタンス
にログインしていない場合は,次でログインして下さい。ローカル環境のターミナルssh アプリ名5.1 Nginx の設定
以下の順序で実行していきます。
- サーバーをアップデート
Nginx
のインストールNginx
の起動とインスタンス起動時自動起動の設定サーバー環境のターミナルsudo yum -y update sudo amazon-linux-extras install -y nginx1 sudo systemctl start nginx sudo systemctl enable nginxブラウザに
Elastic IP
を入力してアクセスしましょう。
Welcome to nginx on Amazon Linux!
が表示されればOKです。【補足】ここでアクセスできない場合は,以下の可能性があります
- 2.5で作成した「EC2 用のセキュリティグループ(アプリ名_ec2_security_group)」の設定を間違えている
- 「タイプが HTTP, ソースが
0.0.0.0/0
と::/0
」のものが含まれているかを確認。「HTTP」を「HTTPS」にしているミスを見かけます- 4.1で設定したEC2 用のセキュリティグループが「アプリ名_ec2_security_group」になっていない
5.2 必要なプラグインのインストール
- 各種プラグインのインストール
- 1行のコマンドです
サーバー環境のターミナルsudo yum -y install git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel ImageMagick ImageMagick-devel【注意】上記はあくまで「画像投稿可能なアプリ」のデプロイを想定したものです。アプリに導入されている gem や ライブラリ次第では,依存関係にある他のプラグインもインストールしておく必要があります。
5.3 データベースにログイン
まず,
EC2
にプリインストールされているMariaDB
を削除しておきましょう。サーバー環境のターミナルsudo yum -y remove mariadb-libsMySQLの場合
以下の順序で実行していきます。
MySQL
のリポジトリを追加MySQL
の5.7がインストールされるように変更MySQL
をインストールサーバー環境のターミナルsudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm sudo yum-config-manager --disable mysql80-community sudo yum-config-manager --enable mysql57-community sudo yum -y install mysql-community-client mysql-server mysql-devel次のコマンドでRDSの
MySQL
にログインできます。サーバー環境のターミナルmysql -h エンドポイント -u root -p # RDS の パスワード を入力
mysql>
という表示が出た後に次を実行して下さい。サーバー環境のターミナル(mysql)show databases; # 表示されたデータベース一覧に,「アプリ名_production」が存在していればOK exit【参考】「エンドポイント」は
2.4
で確認したものです。確認できていない場合はRDS
の「データベース」をクリックし,アプリを選択して出てくる「エンドポイント」を確認しましょう。
【補足】もし,データベース一覧に,「アプリ名_production」が存在しない場合は,
exit;
で終了する前に以下を実行してデータベースを作成して下さい。サーバー環境のターミナル(mysql)# 「アプリ名_production」が存在しない場合のみ,次を実行して下さい CREATE DATABASE アプリ名_production;
【参考】 Sequel Proで MySQL に接続する方法
Sequel Pro
(nightly
バージョン) をインストールしていない場合は,次を実行してインストールしましょう。ローカル環境のターミナルbrew cask install homebrew/cask-versions/sequel-pro-nightly
これで,アプリケーションディレクトリに
Sequel Pro.app
が入ります。
- SSHのタブを選択
キー 値 MySQL Host RDSのエンドポイントを記載 Username root Password RDSのパスワードを記載 Database アプリ名_production Port 3306 SSH Host Elastic IPを記載 SSH User EC2のユーザー名を記載 SSH Password 右側の鍵マークボタンをクリックし「~/.ssh/アプリ名.pem」を選択 【参考】
.ssh
は隠しファイルです。隠しファイルを表示するショートカットキーはcommand + shift + .
です。PostgreSQLの場合
単純にインストールするとバージョンが低すぎるので,
amazon-linux-extras
リポジトリからPostgreSQL
のバージョン11を入れることにしましょう。サーバー環境のターミナルsudo amazon-linux-extras install -y postgresql11 yum list | grep postgresql sudo yum -y install postgresql-devel
【補足】PostgreSQLのバージョン12以上を強引に入れることも可能ですが,
postgresql-devel
のインストールが難しいのでお勧めしません。なお,インストール可能な最新バージョンは,amazon-linux-extras | grep postgresql
で確認できます。
次のコマンドでRDSの
PostgreSQL
にログインできます。サーバー環境のターミナルpsql -h エンドポイント -U postgres # RDS の パスワード を入力
postgres=>
という表示が出た後に次を実行して下さい。サーバー環境のターミナル(PostgreSQL)\l # 表示されたデータベース一覧に,「アプリ名_production」が存在していればOK exit;【補足】もし,データベース一覧に,「アプリ名_production」が存在しない場合は,
exit;
で終了する前に以下を実行してデータベースを作成して下さい。サーバー環境のターミナル(PostgreSQL)# 「アプリ名_production」が存在しない場合のみ,次を実行 CREATE DATABASE アプリ名_production;【参考】 Postico で PostgreSQL に接続する方法
インストールしていない場合は,上記サイトの
Download
ボタンをクリックし,zipファイルを解凍して出てくるPostico
をアプリケーションに移動した上で,実行して下さい。
Postico
を起動し,左下の「New Favorite」をクリック
Options
のドロップダウンを開き,Connect via SSH
をクリック
キー 値 Nickname ※任意 (アプリ名_production など) Host RDS のエンドポイントを記載 Port ※不要 User postgres Password RDSのパスワードを記載 Database アプリ名_production SSH Host Elastic IPを記載 User EC2のユーザー名を記載 Password ※不要 Private Key 「Choose」をクリックし,「~/.ssh/アプリ名.pem」を選択 「Connect」を選択し,再度「Connect」を選択
5.4 Node, Yarn のインストール
Node
のインストールサーバー環境のターミナルcurl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash . ~/.nvm/nvm.sh nvm install node node -e "console.log('Running Node.js ' + process.version)"最後のコマンドで
Running Node.js バージョン
が表示されればOKです。
Yarn
のインストールサーバー環境のターミナルcurl -o- -L https://yarnpkg.com/install.sh | bash5.5 Rubyのインストール
rbenv
のインストールサーバー環境のターミナルgit clone https://github.com/sstephenson/rbenv.git ~/.rbenv echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile echo 'eval "$(rbenv init -)"' >> ~/.bash_profile source ~/.bash_profile
ruby-build
のインストールサーバー環境のターミナルgit clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
Ruby
のインストールまず,デプロイするアプリの
Ruby
のバージョンを確認して下さい。(
ローカル環境のターミナル
でアプリのディレクトリまで移動しruby -v
で確認できます)以下は,バージョンが
2.6.6
の場合の例です。バージョンはアプリに「必ず」合わせて下さい。サーバー環境のターミナルrbenv install 2.6.6 rbenv global 2.6.6 rbenv rehash
Ruby
のインストールには時間がかかります。
Bundler
のインストールサーバー環境のターミナルgem install bundler
完了後に以下を実行し,全てバージョンが表示されればOKです。
サーバー環境のターミナルrbenv -v ruby -v yarn -v bundler -v5.6 デプロイ先ディレクトリの設定
(デフォルト設定の場合)
Capistrano
によるアプリのデプロイ先は/var/www/アプリ名
ディレクトリになります。そこで,このディレクトリをあらかじめ作成しておき,必要な権限を与えておきましょう。
サーバー環境のターミナルsudo mkdir -p /var/www/$APP_NAME sudo chown `whoami`:`whoami` /var/www/$APP_NAME ls -l /var/www最後のコマンドで
drwxr-xr-x 2 ユーザー名 ユーザー名 日付 アプリ名
が表示されればOKです。5.7 Git の初期設定
次に,サーバー環境で
GitHub
の操作ができるようにしていきましょう。まずは,サーバー環境の
Git
の初期設定を行いましょう。ここでは,ローカル環境と同じ「ユーザー名」「メールアドレス」を登録することとしておきます。まず, Git に登録した名前とメールアドレスを確認しましょう。
ローカル環境のターミナルcat ~/.gitconfig
次の箇所をコピーして下さい。
出力内容の一部[user] name = ~~~~~ email = ~~~~~@~~~.~~~
.gitconfig
ファイルの生成サーバー環境のターミナルcd vi .gitconfig
- Vimが開いたら先ほどコピーしたものをペーストしましょう。
5.8 GitHub連携
サーバー環境に GitHub へのアクセス権限を持たせるため,必要な公開鍵・秘密鍵を生成しましょう。
サーバー環境のターミナルcd .ssh ssh-keygen -t rsa -f "${APP_NAME}_git_rsa" -N ""
これで,以下のファイルが作成されます
- 公開鍵(GitHubに配置する鍵)
アプリ名_git_rsa.pub
- 秘密鍵(EC2に残しておく鍵)
アプリ名_git_rsa
config
ファイルの生成サーバー環境のターミナルvi config
- Vimでファイルが開かれたら次を追加
- 「アプリ名」の箇所は各自の設定に合わせること
~/.ssh/configHost github github.com Hostname github.com User git IdentityFile ~/.ssh/アプリ名_git_rsa
- GitHubに公開鍵を登録
以下を実行し,値をコピーしておきましょう。
サーバー環境のターミナル(~/.ssh)cat "${APP_NAME}_git_rsa.pub"
- ブラウザでGitHubにアクセス
- 右上のサムネイル画像をクリック
- 「Settings」をクリック
- 左メニューバーから「SSH and GPG keys」をクリック
- 「SSH Keys」の「New SSH key」をクリック
キー 値 Title アプリ名_git_rsa.pub Key サーバー環境のターミナルからコピーした値をペースト 「Add SSH key」ボタンをクリック
- サーバーから GitHub に接続できるか確認
サーバー環境のターミナル(~/.ssh)chmod 600 config ssh github
yes
を入力し,次の赤枠の内容が出力されればOKです。6. デプロイ(Capistrano)
Capistrano
を使い,1コマンドで Rails アプリをAWS EC2
にデプロイできる状態にしていきましょう。サンプルのアプリをデプロイされたい場合は
6.1
から進めて下さい。オリジナルのアプリをデプロイされる場合は6.2
から進めて下さい。なお,オリジナルアプリのデプロイについては,以下の条件を改めて確認しておいて下さい。
- Rails
6
であること- アプリで使用するデータベースシステムの指定が
RDS
と一致していること
- 他のデータベースを指定している場合は
config/database.yml
を修正して下さい。rails db:system:change --to=mysql
もしくはrails db:system:change --to=postgresql
コマンドが便利です- アプリで使用する gem やライブラリ次第では
EC2
に他にもあらかじめインストールしておく必要がある可能性があります6.1 Railsのサンプルアプリを作成
【注】 「サンプルのアプリ」で AWS のデプロイに挑戦されたい方以外はスキップして下さい。
CarrierWave
を用いた画像投稿機能を持つアプリを簡単に実装しましょう。アプリの作成(MySQLの場合)
ターミナルrails new aws_sample_app -d mysql -C -M -T --skip-active-storageアプリの作成(PostgreSQLの場合)
ターミナルrails new aws_sample_app -d postgresql -C -M -T --skip-active-storage※ 以下は MySQL, PostgreSQL 共通です
ターミナルcd aws_sample_app git add . git commit -m "init" bundle remove jbuilder bundle add carrierwave rails g scaffold Post title:string image:string --skip-assets --skip-helper rails db:migrate:reset rails g uploader Image echo "/public/uploads/" >> .gitignore
- トップページを設定
config/routes.rbRails.application.routes.draw do # ********** 以下を追加 ********** root to: 'posts#index' # ********** 以上を追加 ********** resources :posts end
- 画像投稿機能を付けるための準備
app/models/post.rbclass Post < ApplicationRecord # ********** 以下を追加 ********** mount_uploader :image, ImageUploader # ********** 以上を追加 ********** end
- 投稿する画像の選択ボタンを作成
app/views/posts/_form.html.erb<!-- 略 --> <div class="field"> <%= form.label :image %> <!-- ********** 「<%= form.text_field :image %>」を変更 ********** --> <%= form.file_field :image, accept: "image/png,image/jpeg,image/gif" %> <!-- ********** 以上を変更 ********** --> </div> <!-- 略 -->
- 投稿詳細ページで,投稿した画像が表示されるように設定
app/views/posts/show.html.erb<p id="notice"><%= notice %></p> <p> <strong>Title:</strong> <%= @post.title %> </p> <!-- ********** 以下を編集 ********** --> <% if @post.image? %> <p> <%= image_tag @post.image.url %> </p> <% end %> <!-- ********** 以上を編集 ********** --> <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %>動作確認を行った上で,GitHubにリポジトリを作成し,add, commit を行い, GitHub に push しましょう。
さらに,画像を
AWS S3
に保存できるようにすべきですが,ひとまず画像投稿は可能ですのでデプロイ完了後の10章・11章で設定を行うこととしましょう。6.2. データベースの設定
※以下は自作アプリの場合の場合も実行して下さい。必要があれば作業前にブランチを切るようにしましょう。
ファイル名 ファイルのイメージ config/master.key 鍵 config/credentials.yml.enc 錠付きファイル まず,本番環境用の
config/database.yml
を修正しておきましょう。
RDS
のパスワードとエンドポイントはGitHub
から見られないようにするため,credentials.yml.enc
に記載し,これを読み込むように設定することとします。(
dotenv-rails
を導入し.env
にパスワードなどを記載する方法もあります)MySQLの場合
config/database.ymlproduction: <<: *default # ***** 以下を修正 ***** database: アプリ名_production password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:hostname] %>PostgreSQLの場合
config/database.ymlproduction: <<: *default # ***** 以下を修正 ***** database: アプリ名_production username: postgres password: <%= Rails.application.credentials.db[:password] %> host: <%= Rails.application.credentials.db[:hostname] %>※ 以下は MySQL, PostgreSQL 共通です
database.yml
で読み込むパスワードとエンドポイントをcredentials.yml.enc
に記載しましょう
yaml
形式ですので,インデント幅にはくれぐれも注意して下さい- 例えば,
password:
の後に「半角スペース1個」がないだけでエラーになりますローカル環境のターミナルEDITOR=vi rails credentials:editconfig/credentials.yml.encdb: password: RDSのパスワード hostname: RDSのエンドポイントさらに,本番環境で
master.key
が存在しない場合はエラーが出るように設定しておきます。config/environments/production.rb# 次のコメントアウトを解除 config.require_master_key = true念のため以下を実行し,パスワードとエンドポイントが取得できることを確認しておいた方がよいでしょう。
ローカル環境のターミナルrails c # コンソール起動後 Rails.application.credentials.db[:password] Rails.application.credentials.db[:hostname] # RDSのパスワード, エンドポイントが表示されることを確認後 exit確認ができれば,add, commit を行い, GitHub に push しましょう。
master(main) ブランチ以外で作業をされている場合は,プルリクを出し,GitHubの master(main) ブランチにマージするところまでは行ってください。
6.3. Capistrano
1コマンドで Rails アプリをデプロイできるよう
Capistrano
を導入しましょう。Gemfilegroup :development do # 略 # ***** 以下を追加 ***** gem "capistrano", "~> 3.10", require: false gem "capistrano-rails", "~> 1.6", require: false gem 'capistrano-rbenv', '~> 2.2' gem 'capistrano-rbenv-vars', '~> 0.1' gem 'capistrano3-puma' # ***** 以上を追加 ***** endローカル環境のターミナルbundle install bundle exec cap install STAGES=production
Capfile
の# require "capistrano/passenger"
の下に以下を追加Capfilerequire 'capistrano/rbenv' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano/puma' install_plugin Capistrano::Puma install_plugin Capistrano::Puma::Nginx
- デプロイの設定ファイルを修正・追記しましょう
- 「アプリ名」「GitHubリポジトリURL」は各自のものに置き換えて下さい
- 「GitHubリポジトリURL」は
HTTPS
でなくSSH
のURLをコピペして下さいconfig/deploy.rb# config valid for current version and patch releases of Capistrano lock "~> 3.14.1" # ***** 以下を修正 ***** set :application, "アプリ名" set :repo_url, "GitHubのリポジトリURL" set :rbenv_ruby, File.read('.ruby-version').strip # Nginxの設定ファイル名と置き場所を修正 set :nginx_config_name, "#{fetch(:application)}.conf" set :nginx_sites_enabled_path, "/etc/nginx/conf.d" append :linked_files, "config/master.key" append :linked_dirs, "log", "tmp/pids", "tmp/cache", "tmp/sockets", "node_modules" # ***** 以上を追加 *****
production.rb
の一番上に,EC2サーバーにログインするユーザー名、サーバーのロールを記述
- 「ElatsticIP」「アプリ名」「ユーザー名」は各自のものに置き換えること
config/deploy/production.rbserver "ElatsticIP", user: "ユーザー名", roles: %w{app db web} set :ssh_options, { keys: %w(~/.ssh/アプリ名.pem), forward_agent: true, auth_methods: %w(publickey), }master.key の配置と Rails アプリのデプロイ
準備が整いましたので,Railsアプリのデプロイを行いましょう。
初回の実行では
master.key
がないためデプロイに失敗しますが,master.key
を配置するために必要なディレクトリが生成されます。デプロイ失敗後に
scp
コマンドでmaster.key
をサーバー側に追加し,再度実行すればデプロイに成功するでしょう。ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production deploy # 「ERROR linked file /var/www/アプリ名/shared/config/master.key does not exist on ElasticIP」が出ればOK scp config/master.key $APP_NAME:/var/www/$APP_NAME/shared/config bundle exec cap production deploy最後から2行目に
Command restart sent success
が表示されていればOKです。【備考】ここでデプロイに失敗した場合は,まずエラー文を確認しましょう。いろいろなケースがありますが,アプリで使用されている gem 次第では,先に依存関係にあるプラグインを EC2 にインストールしておく必要があります。
Nginx の設定
Nginx
用の設定ファイルを追加するため,先に必要なディレクトリをサーバー側で作成しておきましょう。サーバー環境のターミナルcd /etc/nginx sudo mkdir sites-available
ローカル環境
のターミナルで,Railsアプリのルートディレクトリまで移動した後,以下を実行しましょう。
これでNginx
用の設定が生成されます。ローカル環境のターミナル# Railsアプリのルートディレクトリに移動してから bundle exec cap production puma:nginx_configこれで,サーバー側の
/etc/nginx/conf.d
に設定ファイルアプリ名.conf
が入ります。
Nginx
を再起動しましょう。サーバー環境のターミナル(/etc/nginx)sudo service nginx restart
ブラウザのアドレスバーに
Elastic IP
を入力してアクセスし,スーパーリロード
して下さい。(ショートカットキーはcommand + shift + r
)アプリが表示されればOKです!
【補足】アプリが表示されない場合は,以下を試して下さい
- ローカル環境のターミナルから
curl -I ElasticIP
を実行したとき,最初にHTTP/1.1 301 Moved Permanently
が出力される場合
config/environments/production.rb
のconfig.force_ssl = true
をコメントアウトして下さい9.4
にログの確認方法を記載していますので,確かめてみましょう!!
これでひとまずデプロイは完了です!……が,他にもすべきことがありますので, 【後半】 に進みましょう。
「無事デプロイに成功した!!」という方は是非 LGTM もお願いいたします!
- 投稿日:2020-11-26T17:58:59+09:00
RailsアプリをHerokuでデプロイしてみた。
Railsでアプリケーションを作成してみたのでHerokuでデプロイしてみました。
下の方のを参考にしたらなんなく出来ました!アウトプットの為に投稿させてもらいます。
【初心者向け】railsアプリをherokuを使って確実にデプロイする方法【決定版】
自分はPostgreSQLを使って作っていたので最初の設定はスルーして実装しました。
gitも入っていたので省略します。環境
Rails 5.2.1
Ruby 2.6.5
git 2.23.0
heroku/7.47.3 darwin-x64 node-v12.16.2Herokuとは
PaaS(Platform as a Service)と呼ばれるサービス
開発したwebアプリケーションを開発、実行するための基盤(プラットフォーム)を提供するサービス
無料で使用する事が可能で簡単にデプロイ出来ちゃいます。Herokuの登録
日本語翻訳の方がありましたのでこちらからどうぞ!
パスワードはターミナルでログインする際に使いますので忘れない様に!
https://signup.heroku.com/jp
会員登録が終わったら、PCとHerokuを紐づける為にcliをダウンロードします。OSで違いが出るのはここぐらいです!
https://devcenter.heroku.com/articles/heroku-cliHerokuが入っているか確認
$heroku --version >> heroku/7.47.3 darwin-x64 node-v12.16.2PCとHerokuの紐付け
$heroku loginメールアドレスとパスワードを入力します!
Enter your Heroku credentials: Email: ~~~~~@example.com (登録したメールアドレスを) Password: ********** (登録したパスワードを) Logged in as ~~~~~@example.comURLがアプリ名になります
$heroku create アプリ名Herokuにデプロイする
$git push heroku main or master ←自分のブランチ名によります本番環境のマイグレーション
$heroku run rails db:migrateこれで特にエラーとかでなければ作成されたURLを叩いてみましょう!
※自分はHerokuにデプロイする時に以下のエラーが出ましたerror: src refspec master does not match any error: failed to push some refs to 'アプリURL.git'自分のgitにはmasterというブランチはなくmainというブランチだったのでエラーが出てました。
- 投稿日:2020-11-26T16:46:43+09:00
[Rails]Request Specでのログインの実施
はじめに
アプリ開発において、トップページ以外ログインをしていないと見れないという設定にしていたので、postsコントローラーのshowアクションのテストコードの際に利用しました。
目次
- 1. deviseのヘルパー機能を呼び出す設定
- 2. FactoryBotを利用したdevise認証
1. deviseのヘルパー機能を呼び出す設定
spec/rails_helper.rbRSpec.configure do |config| ~略~ #下記を追記 config.include Devise::Test::IntegrationHelpers, type: :request ~略~ end2. FactoryBotを利用したdevise認証
FactoryBotを利用できるように設定します。
spec配下にsupportディレクトリを作成しfactory_bot.rbファイルを作成します。spec/support/factory_bot.rbRSpec.configure do |config| config.include FactoryBot::Syntax::Methods end下記の一文のコメントアウトを外して有効にします。
spec/rails_helper.rb~略~ Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f } ~略~FactoryBotを用いてテスト用のuserを作成します。
spec/factories/users.rbFactoryBot.define do factory :user do nickname { Faker::Name.last_name } email { Faker::Internet.free_email } password = Faker::Internet.password(min_length: 6) password { password } password_confirmation { password } birthday { Faker::Date.in_date_period } gender { 2 } end endbefore do ~ endでユーザーログインまでの挙動を設定しています。
spec/requests/posts_request_spec.rbrequire 'rails_helper' RSpec.describe 'Posts', type: :request do before do # 登録しているuserを使うのでcreateとします。 @user = FactoryBot.create(:user) # deviseのメソッドであるsign_inでログインしています。 sign_in @user @post = FactoryBot.create(:post, image: fixture_file_upload('public/images/test_image.png')) end describe "GET #show" do it "showアクションにリクエストすると正常にレスポンスが返ってくる" do get post_path(@post) expect(response.status).to eq 200 end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミの商品名が存在する" do get post_path(@post) expect(response.body).to include @post.name end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミのカテゴリーが存在する" do get post_path(@post) expect(response.body).to include @post.category.name end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミの更新日が存在する" do get post_path(@post) expect(response.body).to include @post.created_at.strftime("%Y.%m.%d") end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミの投稿者名が存在する" do get post_path(@post) expect(response.body).to include @post.user.nickname end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミの評価が存在する" do get post_path(@post) expect(response.body).to include "#{@post.evaluation}" end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミ商品購入額が存在する" do get post_path(@post) expect(response.body).to include "#{@post.price}" end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミ商品購入店が存在する" do get post_path(@post) expect(response.body).to include @post.shop_name end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミレビュー文が存在する" do get post_path(@post) expect(response.body).to include @post.description end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミの画像が存在する" do get post_path(@post) expect(response.body).to include 'test_image.png' end it "showアクションにリクエストするとレスポンスに投稿済みのクチコミのお気に入り数が存在する" do get post_path(@post) expect(response.body).to include "#{@post.likes.count}" end it "showアクションにリクエストするとレスポンスに関連商品のクチコミ表示部分が存在する" do get post_path(@post) expect(response.body).to include '関連商品のクチコミ' end end end参考リンク
- 投稿日:2020-11-26T16:08:42+09:00
Rails+Bootstrapでtodoアプリを作ってみよう
はじめに
プログラミングを初めてまず最初に作るアプリはtodoアプリなのではないでしょうか。一度理解してしまえばなんてことはない簡単なアプリですが理解するまでが意外と大変だと思います。そんなtodoアプリをrailsとbootstrapを使って制作していきましょう!
バージョン
Rails 6.0.3.4
Ruby 2.6.3
Bootstrap 3.3.6プロジェクトの作成
それでは早速進めていきましょう。ターミナルに
ターミナル$rails new todo-appと打ってプロジェクトを作成させます。途中、passwordを求められますので忘れずに入力してください。その際、入力した文字が画面に表示されませんが構わずに続けてEnterを押して進んでください。
Webpacker successfully installed ? ?
と表示されればプロジェクト作成は完了です。ケーキ食べたい...(途中Warningがたくさん出てくるかもしれませんがErrorと出てこない限りは全部無視してしまって大丈夫です。)その後
ターミナル$cd todo-appと入力してtodo-appに移動しましょう。(この後の作業は全てtodo-appに移動している前提で行います。)
モデルの作成
モデルを作成していきます。モデルは単数形で頭文字を大文字にするのがルールです。ここではtitleをstring型、bodyをtext型にして作っていきたいと思います。ターミナルで以下を実行してください。
ターミナル$rails g model Task title:string body:textできたらその後以下でマイグレートしましょう。(もし間違えて作成してしまった場合には、gをdに変えて実行すれば消すことができます。)
ターミナル$rails db:migrateコントローラの作成
コントローラを作ります。コントローラは複数形で全て小文字にするのがルールです。
ターミナル$rails g controller tasksこれで、大まかな構造を作ることができました。(もし間違えて作成してしまった場合には、モデルと同じくgをdに変えて実行すれば消すことができます。)次からコードを打ち込んでいきましょう!!
トップ画面 ~index~
それでは、まずはトップ画面を作成していきたいと思います。トップ画面にはやること一覧を表示させます。これにはindexアクションを用いましょう。ここではすべてのタスクをTask.allで取得します。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end end次にviewを作成していきましょう。viewsフォルダのなかのtasksフォルダの中にindex.html.erbというファイルを作りましょう。(controlを押しながらクリックすれば作成できます。)ファイルを作ることができたら以下を記述しましょう。
app/views/tasks/index.html.erb<h1>やること一覧</h1> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> </tr> <% end %> </tbody> </table>次に大事なルーティングを作成しましょう。以下のように記述してください。
config/routes.rbresources :tasksなんとなんとrailsだとこの1行でindex,new,create,edit,update,show,destroyの主要な7つのアクション一気に作ることができます。(今回showは使いませんが...)rails便利!
これからは、localhost:3000/tasksと打てば今作成している画面を確認できるようになります。エラーが起きていないか常に確認しながら進めていきましょう。
新規作成機能 ~new,create~
ここからは新規作成機能を作っていきましょう。まずはコントローラに記述をしていきます。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end #ここから追加 def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path #セーブできたらindexページに行く else render 'new' #できなかったらnewページのまま end end private def task_params #モデル作成時に作ったやつ params.require(:task).permit(:title, :body) end endここではストロングパラメータというものを使って、Taskモデルを作成した際にできたtaskテーブルににtitle(やること)とbody(詳細)を保存します。ストロングパラメータについて詳しく知りたいかたはこちらを参照してください。そして「redirect toとrenderの違いって何??」と思ったセンスの良いかたはこちらを参照してください。
viewを作成します。
app/views/tasks/new.html.erb<h1>やること新規作成</h1> <%= link_to '一覧へ', tasks_path %> <%= form_with model: @task do |f| %> <div class="field"> <%= f.label :やること %><br> <%= f.textarea_field :title %> </div> <div class="field"> <%= f.label :詳細 %><br> <%= f.text_field :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>form_withを使ってデータを保存させます。form_withについて詳しく知りたいかたはこちら
これによって作られたデータは、createアクションへ運ばれます。ここで、フォームが空欄だった場合に保存できないようにしておきましょう。この機能をバリデーションと呼びます。
app/model/task.rbclass Task < ApplicationRecord validates :title, presence: true validates :body, presence: true end詳しい説明はここでは省きますが、これで空欄のままsubmitを押しても保存されないようになります。バリデーションについて詳しくしれたい方はこちら
最後にindexのページ(やること一覧のページ)に新規作成ページへのリンクを貼り付けましょう。ターミナルで
ターミナル$rails routesと打ってみてください。すると、
ターミナルtasks GET /tasks(.:format) tasks#index POST /tasks(.:format) tasks#create new_task GET /tasks/new(.:format) tasks#new edit_task GET /tasks/:id/edit(.:format) tasks#edit task GET /tasks/:id(.:format) tasks#show PATCH /tasks/:id(.:format) tasks#update PUT /tasks/:id(.:format) tasks#update DELETE /tasks/:id(.:format) tasks#destroy ...と出てきたと思います。このtasks#newの左側にあるnew_taskにpathをくっつけたのがnewページに行くためのリンクになります。そのため、
app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> #追加 <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> </tr> <% end %> </tbody> </table>これで新規作成機能は終わりです。
編集機能 ~edit,update~
続いて、編集機能を作成していきたいと思います。編集にはeditアクションとupdateアクションを使用します。コントローラーにこの2つのアクションを記述していきましょう。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path else render 'new' end end #ここから追加 def edit @task = Task.find(params[:id]) end def update @task = Task.find(params[:id]) if @task.update(task_params) redirect_to tasks_path #updateできたらindexページに行く else render 'edit' #できなかったらeditページのまま end end #ここまで private def task_params params.require(:task).permit(:title, :body) end endここで新しく、find(params[:id])というコードが出てきましたね。これは投稿され情報に付けられたidを探し出すコードです。例えば、「ケーキを買う」という内容を編集したいのにボタン押したら隣に記述していた「部屋の掃除をする」という内容が画面に出てきたらもう訳わかんないですよね。ここではこのfind(params[:id])を使って編集したい内容を正しく呼び出せるようにしています。(ちなみにrailsというフレームワークを使っているからこの1行だけで情報を呼び出せるのであり、使はなければSQLという言語をゴリゴリ書く必要があります。railsすげえ。)
次にviewsファイルを作成していきましょう。
app/views/tasks/edit.html.erb<h1>やること編集</h1> <%= link_to '一覧へ', tasks_path %> <%= form_with model: @task do |f| %> <div class="field"> <%= f.label :やること %><br> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :詳細 %><br> <%= f.text_field :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>入力フォームなのでnew.html.erbと同じコードですね。最後に一覧画面に編集画面へのリンクを付け加えて終了です。
app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> <td><%= link_to '編集', edit_task_path(task) %></td> #追加 </tr> <% end %> </tbody> </table>pathはターミナルでrails routesと打って確認してみてください。(新規作成機能作る時に一回やったやつ。)edit画面へ遷移する時にはidが必要なので今この情報を持っているtaskを最後につけることを忘れずに。
これで編集機能は終わりです。
削除機能 ~destroy~
最後は削除機能を作成していきます。コントローラーにdestroyアクションを追加しましょう。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path else render 'new' end end def edit @task = Task.find(params[:id]) end def update @task = Task.find(params[:id]) if @task.update(task_params) redirect_to tasks_path else render 'edit' end end #ここから追加 def destroy @task = Task.find(params[:id]) @task.destroy redirect_to tasks_path end #ここまで private def task_params params.require(:task).permit(:title, :body) end endここではfind(params[:id])で削除する情報を見つけて、destroyで削除しています。
一覧画面に削除ボタンを付けましょう。app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> <td><%= link_to '編集', edit_task_path(task) %></td> <td><%= link_to '削除', task, method: :delete, data: { confirm: '本当に削除しますか?' } %></td> </tr> </tr> <% end %> </tbody> </table>ここではpath名ではなく、method: :deleteと記述することでdestroyアクションを呼びます。そして、data: { confirm: '本当に削除しますか?' }と記述することで確認のモーダルウィンドウを出すことができます。
以上でtodoアプリの機能は全て作ることができました。お疲れ様でした。?
Bootstrapを使ってレイアウトを整えよう
これでtodoアプリは完成したのですが、レイアウトがちょっと味気ないですよね...そこでBootstrapというcssのフレームワークを導入してレイアウトを整えていきましょう!
下準備
Gemfilegem 'bootstrap-sass', '~> 3.3.6' gem 'jquery-rails'と入力し、
ターミナル$bundle installとしましょう。途中passwordを求められると思うので指示通り入力してください。
次にRailsアプリの作成時に生成される
application.css
をapplication.scss
にリネームしてください。このファイルはapp/assert/stylesheet/の下にあります。ファイル名を変更できたら、
app/assert/stylesheet/application.scss@import "bootstrap-sprockets"; @import "bootstrap";これらを追加してください。
そして、最後にapplication.jsを編集します。
app/javascript/application.js//= require jquery //= require bootstrap-sprocketsまたこれらをを追加してください。これでrailsでbootstrapを使うための下準備が完了しました。
レイアウトを整える
早速やっていきましょう。
まず、画面が左に偏っていると思うので真ん中にいい感じになるようにしましょう。(語彙力なくてごめんなさい。)application.html.erbにある<%= yield %>を以下のようにdivタグで囲んで下さい。
views/layout/application.html.erb<div class="container"> <%= yield %> </div>この<%= yield %>には、各ページで表示されるhtmlファイルの内容が入ってきます。そのため、ここを編集するだけで全ページに編集を適用させることができます。
これで、レイアウトがいい感じに画面の真ん中にあると思います。
次に一覧ページのtableタグを以下のように編集してください。
app/views/tasks/index.html.erb<table class="table table-striped"> </table>これで投稿された内容の背景が交互に変わり見やすくなっていると思います。(これすごいですよね。初めて使った時感動しました。)
そして最後にボタンをいい感じにしておきましょう。一覧画面にある、新規作成ボタン、編集ボタン、削除ボタンを以下のようにclassを付けて編集してみてください。
app/views/tasks/index.html.erb<%= link_to '新規作成', new_task_path, class: "btn btn-primary" %> <%= link_to '編集', edit_task_path(task), class: "btn btn-success" %> <%= link_to '削除', task, method: :delete, data: { confirm: 'You sure?' }, class: "btn btn-danger" %>ついでに新規作成画面と編集画面にある「一覧へ」ボタンも編集してみましょう。
app/views/tasks/new.html.erbとedit.html.erb<%= link_to '一覧へ', tasks_path, class: "btn btn-info" %>色についてはこちらのサイトに色々(?)書いてあるのでお好みの色を使ってみてください。
これで使いやすいいい感じのレイアウトになったと思います。お疲れ様でした!
最後に
これで使いやすいtodoアプリを作ることができました。たかがtodoアプリではありますが重要な要素がたくさん詰まっているので1つ1つ確認してみてください。
以上、最後まで読んでいただきありがとうございました!!!??
- 投稿日:2020-11-26T16:08:42+09:00
[初心者向け]Railsでtodoアプリを作ってみよう
はじめに
プログラミングを初めてまず最初に作るアプリはtodoアプリだと思います。この基本の「き」とも言えるtodoアプリを一緒に作っていきましょう!
バージョン
Rails 6.0.3.4
ruby 2.6.3プロジェクトの作成
それでは早速進めていきましょう。ターミナルに
ターミナル$rails new todo-appと打ってプロジェクトを作成させます。途中、passwordを求められますので忘れずに入力してください。その際、入力した文字が画面に表示されませんが構わずに続けてEnterを押して進んでください。
Webpacker successfully installed ? ?
と表示されればプロジェクト作成は完了です。ケーキ食べたい...(途中Warningがたくさん出てくるかもしれませんがErrorと出てこない限りは全部無視してしまって大丈夫です。)その後
ターミナル$cd todo-appと入力してtodo-appに移動しましょう。
モデルの作成
モデルを作成していきます。モデルは単数形で頭文字を大文字にするのがルールです。ここではtitleをstring型、bodyをtext型にして作っていきたいと思います。ターミナルで以下を実行してください。
ターミナル$rails g model Task title:string body:textできたらその後以下でマイグレートしましょう。(もし間違えて作成してしまった場合には、gをdに変えて実行すれば消すことができます。)
ターミナル$rails db:migrateコントローラの作成
コントローラを作ります。コントローラは複数形で全て小文字にするのがルールです。
ターミナル$rails g controller tasksこれで、大まかな構造を作ることができました。(もし間違えて作成してしまった場合には、モデルと同じくgをdに変えて実行すれば消すことができます。)次からコードを打ち込んでいきましょう!!
トップ画面 ~index~
それでは、まずはトップ画面を作成していきたいと思います。トップ画面にはやること一覧を表示させます。これにはindexアクションを用いましょう。ここではすべてのタスクをTask.allで取得します。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end end次にviewを作成していきましょう。viewsフォルダのなかのtasksフォルダの中にindex.html.erbというファイルを作りましょう。(controlを押しながらクリックすれば作成できます。)ファイルを作ることができたら以下を記述しましょう。
app/views/tasks/index.html.erb<h1>やること一覧</h1> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> </tr> <% end %> </tbody> </table>次に大事なルーティングを作成しましょう。以下のように記述してください。
config/routes.rbresources :tasksなんとなんとrailsだとこの1行でindex,new,create,edit,update,show,destroyの主要な7つのアクション一気に作ることができます。他の言語だと色々ごちゃごちゃと書かないといけないのですが、、、rails便利ですね。
これからは、localhost:3000/tasksと打てば今作成している画面を確認できるようになります。エラーが起きていないか常に確認しながら進めていきましょう。
新規作成機能 ~new,create~
ここからは新規作成機能を作っていきましょう。まずはコントローラに記述をしていきます。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end #ここから追加 def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path #セーブできたらindexページに行く else render 'new' #できなかったらnewページのまま end end private def task_params #モデル作成時に作ったやつ params.require(:task).permit(:title, :body) end endここではストロングパラメータというものを使って、Taskモデルを作成した際にできたtaskテーブルににtitle(やること)とbody(詳細)を保存します。ストロングパラメータについて詳しく知りたいかたはこちらを参照してください。そして「redirect toとrenderの違いって何??」と思ったセンスの良いかたはこちらを参照してください。
viewを作成します。
app/views/tasks/new.html.erb<h1>やること新規作成</h1> <%= link_to '一覧へ', tasks_path %> <%= form_with model: @task do |f| %> <div class="field"> <%= f.label :やること %><br> <%= f.textarea_field :title %> </div> <div class="field"> <%= f.label :詳細 %><br> <%= f.text_field :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %>form_withを使ってデータを保存させます。form_withについて詳しく知りたいかたはこちら
これによって作られたデータは、createアクションへ運ばれます。ここで、フォームが空欄だった場合に保存できないようにしておきましょう。この機能をバリデーションと呼びます。
app/model/task.rbclass Task < ApplicationRecord validates :title, presence: true validates :body, presence: true end詳しい説明はここでは省きますが、これで空欄のままsubmitを押しても保存されないようになります。バリデーションについて詳しくしれたい方はこちら
最後にindexのページ(やること一覧のページ)に新規作成ページへのリンクを貼り付けましょう。ターミナルで
ターミナル$rails routesと打ってみてください。すると、
ターミナルtasks GET /tasks(.:format) tasks#index POST /tasks(.:format) tasks#create new_task GET /tasks/new(.:format) tasks#new edit_task GET /tasks/:id/edit(.:format) tasks#edit task GET /tasks/:id(.:format) tasks#show PATCH /tasks/:id(.:format) tasks#update PUT /tasks/:id(.:format) tasks#update DELETE /tasks/:id(.:format) tasks#destroy ...と出てきたと思います。このtasks#newの左側にあるnew_taskにpathをくっつけたのがnewページに行くためのリンクになります。そのため、
app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> #追加 <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> </tr> <% end %> </tbody> </table>これでtopページと新規作成機能は終わりです。
編集機能 ~edit,update~
続いて、編集機能を作成していきたいと思います。編集にはeditアクションとupdateアクションを使用します。コントローラーにこの2つのアクションを記述していきましょう。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path else render 'new' end end #ここから追加 def edit @task = Task.find(params[:id]) end def update @task = Task.find(params[:id]) if @task.update(task_params) redirect_to tasks_path #updateできたらindexページに行く else render 'edit' #できなかったらeditページのまま end end #ここまで private def task_params params.require(:task).permit(:title, :body) end endここで新しく、find(params[:id])というコードが出てきましたね。これは投稿され情報に付けられたidを探し出すコードです。例えば、「ケーキを買う」という内容を編集したいのにボタン押したら隣に記述していた「部屋の掃除をする」という内容が画面に出てきたらもう訳わかんないですよね。ここではこのfind(params[:id])を使って編集したい内容を正しく呼び出せるようにしています。(ちなみにrailsというフレームワークを使っているからこの1行だけで情報を呼び出せるのであり、使はなければSQLという言語をゴリゴリ書く必要があります。railsすげえ。)
次にviewsファイルを作成していきましょう。
app/views/tasks/edit.html.erb<h1>やること編集</h1> <%= form_with model: @task do |f| %> <div class="field"> <%= f.label :やること %><br> <%= f.text_field :title %> </div> <div class="field"> <%= f.label :詳細 %><br> <%= f.text_field :body %> </div> <div class="actions"> <%= f.submit %> </div> <% end %> <%= link_to '一覧へ', tasks_path %>入力フォームなのでnew.html.erbと同じコードですね。最後に一覧画面に編集画面へのリンクを付け加えて終了です。
app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> <td><%= link_to '編集', edit_task_path(task) %></td> #追加 </tr> <% end %> </tbody> </table>pathはターミナルでrails routesと打って確認してみてください。(新規作成機能作る時に一回やったやつ。)edit画面へ遷移する時にはidが必要なので今この情報を持っているtaskを最後につけることを忘れずに。
これで編集機能は終わりです。
削除機能 ~destroy~
最後は削除機能を作成していきます。コントローラーにdestroyアクションを追加しましょう。
app/controllers/tasks_controller.rbclass TasksController < ApplicationController def index @tasks = Task.all end def new @task = Task.new end def create @task = Task.new(task_params) if @task.save redirect_to tasks_path else render 'new' end end def edit @task = Task.find(params[:id]) end def update @task = Task.find(params[:id]) if @task.update(task_params) redirect_to tasks_path else render 'edit' end end #ここから追加 def destroy @task = Task.find(params[:id]) @task.destroy redirect_to tasks_path end #ここまで private def task_params params.require(:task).permit(:title, :body) end endここではfind(params[:id])で削除する情報を見つけて、destroyで削除しています。
一覧画面に削除ボタンを付けましょう。app/views/tasks/index.html.erb<h1>やること一覧</h1> <%= link_to '新規作成', new_task_path %> <table> <thead> <tr> <th>やること</th> <th>詳細</th> </tr> </thead> <tbody> <% @tasks.each do |task| %> <tr> <td><%= task.title %></td> <td><%= task.body %></td> <td><%= link_to '編集', edit_task_path(task) %></td> <td><%= link_to '削除', task, method: :delete, data: { confirm: '本当に削除しますか?' } %></td> </tr> </tr> <% end %> </tbody> </table>ここではpath名ではなく、method: :deleteと記述することでdestroyアクションを呼びます。そして、data: { confirm: '本当に削除しますか?' }と記述することで確認のモーダルウィンドウを出すことができます。
最後に
お疲れ様です。以上でtodoアプリを作ることができました。たかがtodoアプリではありますが大事な要素が色々詰まっているので1つ1つ確認してみてください。
以上、最後まで読んでいただきありがとうございました!!!??
- 投稿日:2020-11-26T15:31:57+09:00
既存プロジェクトへのRidgepole導入
導入手順
Gemfile
gem 'ridgepole'
db/config.yml
development: adapter: mysql2 encoding: utf8 database: xxxx_development pool: 5 username: root timeout: 5000 host: 127.0.0.1 port: 3306 test: adapter: mysql2 encoding: utf8 database: xxxx_test pool: 5 username: root timeout: 5000 host: 127.0.0.1 port: 3306
- スキーマファイル出力
bundle exec ridgepole -c db/config.yml --export -o db/Schemafileマイグレーションの適用
- diff/差分表示
bundle exec ridgepole --diff db/config.yml db/Schemafile
- プレビュー
bundle exec ridgepole --config db/config.yml --file db/Schemafile --apply --dry-run ---------- Apply `db/Schemafile` (dry-run) No change
- 実適用
bundle exec ridgepole --config db/config.yml --file db/Schemafile --apply ---------- Apply `db/Schemafile` No change
- 投稿日:2020-11-26T15:06:04+09:00
railsにSlimを導入する
Gemfilegem 'slim-rails' gem 'html2slim'bundleレイアウトファイルをSlimに変更する
bundle exec erb2slim app/views/layouts/ --delete
- 投稿日:2020-11-26T12:57:21+09:00
EC2で自動デプロイが反映されなくなったときの対処法
はじめに
現象
いつもどおり自動デプロイしたはずがまったく反映されない
やってみて
EC2インスタンスがおかしいのかなと思って再起動してみたら無事解決。
再起動に必要なコマンドを備忘します。手順
EC2インスタンスを再起動
AWSコンソールからEC2インスタンスを再起動します。
DBを起動させる
EC2を再起動するとDBが停止状態になるので起動させます。
(私はMariaDBを使用しています)確認コマンド
ターミナル(EC2)$ sudo systemctl status mariadb結果
ターミナル(EC2)● mariadb.service - MariaDB database server Loaded: loaded (/usr/lib/systemd/system/mariadb.service; disabled; vendor preset: disabled) Active: inactive (dead)死んじゃってるのが確認できます。
DB起動コマンド
ターミナル(EC2)$ sudo systemctl start mariadbこれで確認するとActiveになっているはずです。
Nginxを起動させる
同じようにNginxも起動させます。
Nginx起動コマンド
ターミナル(EC2)$ sudo systemctl start nginx改めて自動デプロイを行う
これが本当に正解なのかわからないところがありますが(1度目の自動デプロイの内容をEC2が読み込めているなら、Unicornの起動だけでいいような気がします)
とりあえず自動デプロイを行えばEC2に反映されますし、Unicornも起動されるのでもう一度コマンドを打ちます。
ターミナル(ローカル)% bundle exec cap production deployこれにて一件落着です。
おわりに
本当にこの画面が嫌いです。
✔︎
- 投稿日:2020-11-26T12:03:20+09:00
rubocopを導入してみた
始めに
rubocopはRubyで書いたコードが規則に従っているかを自動的にチェックしてくれるコーディングチェックツールです。Rubyはシンプルかつ多様な書き方が出来る言語なのでエンジニアによっては書き方にばらつきが生じます。そこで、rubocopを導入することで、複数人でコーディングをする場合にコードの可読性を保つことが出来るというメリットがあります。勿論一人で開発を進める時でも手軽にコード確認が行えますので、早速導入していきたいと思います。
rubocopのインストール
Gemfileに以下の二つを記述してからbundle installします。
Gemfile.group :development do <snip> gem 'rubocop', require: false gem 'rubocop-rails' endこれだけで導入が完了できました。
とりあえず使ってみる
このコマンドをアプリがあるディレクトリで実行するだけです。
rubocop実行すると解析が始まり、ディレクトリ内のRubyで書かれたコードはチェックされます。
Inspecting 123 files CCCCCCCCCCCCCCCWCCCCCCCCWCWCCCCCCCCCCCCCCCCCCCCCCCCCWCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCWCCCCCWCCCCCCCCCCCCすごい数の警告が出てきました。
次はこの警告に対応してデバッグをしていきます。
rubocopの設定
以下のコマンドを実行します。
rubocop --auto-gen-configするとこのように2つの設定ファイルが生成されるはずです。
Added inheritance from `.rubocop_todo.yml` in `.rubocop.yml`..rubocop.ymlはコーディングの規則、.rubocop_todo.ymlは修正するべきコードの部分を記述したものであると考えていいでしょう。
.rubocop.ymlの中をいじっていきます。
rubocop.ymlinherit_from: .rubocop_todo.yml require: - rubocop-rails AllCops: TargetRubyVersion: 2.7.1 Exclude: - 'config.ru' - 'bin/**' - 'lib/**' - 'db/**/*' - 'config/**/*' - 'script/**/*' - !ruby/regexp /old_and_unused\.rb$/ AsciiComments: Enabled: false Documentation: Enabled: false ClassAndModuleChildren: Enabled: false Style/FrozenStringLiteralComment: Enabled: false Style/GuardClause: Enabled: falseこの辺の設定は個人やチームによって異なると思います。
修正
rubocopには自動修正機能があります。以下のコマンド実行で修正が始まります。
rubocop -a123 files inspected, 605 offenses detected, 605 offenses correctedかなりの部分が修正されましたが、これで全部ではありません。.rubocop.todo.ymlに書かれた違反部分を消す→rubocop実行→修正のサイクルで進めていくことになると思います。
終わりに
簡単な解説でしたが、無事にrubocopを導入してコードのチェックが出来るようになりました。
参考にさせていただいた記事
- 投稿日:2020-11-26T10:46:41+09:00
【Rails】部分テンプレート(render)で別のコントローラーのビューを呼び出す方法
はじめに
違うファイルのビューを他のファイルのビューに表示さる際、部分的にそのビューをrenderで呼びだすことができます。
そんな、部分テンプレートの方法について紹介します。目次
- 部分テンプレートファイルの名前について
- renderで呼び出す
- コントローラーへの定義
開発環境
ruby 2.6.5
rails 6.0.0実装
それでは実装していきます〜
1. 部分テンプレートファイルの名前について
まず、部分テンプレートとしてビューファイルを作成する時は
_index.html.erb
のようにファイル名の前に_
(アンダースコア)をつけます。今回はproductsコントローラーのビューを部分テンプレートとして使いたいので、
products/_index
となるようにファイル名を編集すます。2. renderで呼び出す
次にテンプレートする側に
render
メッソドを記述します。
今回は以下の記述をします。app/views/tops/index.html.erb#省略 <%= render partial: "products/index" %>構文はこちらです。
render partial: コントローラー名/ファイル名partialオプションは部分テンプレートを呼び出す時に使います。ただ、強調しているだけ、つけなくても呼び出せます。
これで完成!!と思ったのですが、今回
@products
を定義してProductモデルからデータを取得してビューに表示してる為、topsコントローラーでも定義が必要です。3. コントローラーへの定義
保存したデータを呼び出す場合コントローラーで
インスタンス変数
にデータを代入してビューで使用します。productコントローラーで動かすのであればそちらに
@products
を定義しますが、今回はtopsコントローラのアクションが動くのでそちらで定義する必要があります。app/views/products/_index.html.erb<h1>Products#index</h1> <p>Find me in app/views/products/index.html.erb</p> <div class="#"> <% @products.each do |product| %> #ここで@productsを定義してるので、コントローラーでも定義が必要です。 <%= product.name %> <%= product.text %> <% end %> </div>この
products/_index.html.erb
が部分テンプレートとして呼び出されるので、呼び出された側のtops_contller.rb
でも@products
定義が必要です。app/contollers/tops_contller.rbclass TopsController < ApplicationController def index @tops = Top.all @products = Product.all #部分テンプレートで_index.htmlを表示させる為の定義 endこれで完成です!!!
まとめ
以上部分テンプレートの手順でした。
用途に応じて他にもやり方がありますが、今回はこの方法で実装してます。最後に
私はプログラミング初学者ですが、自分と同じ様にエンジニアを目指す方々の助けになればと思い、記事を投稿しております。
それではまた次回お会いしましょう〜
- 投稿日:2020-11-26T09:09:26+09:00
Cloud9でRuby on Railsの環境構築 ~インストールから起動まで~
はじめに
備忘録としてタイトル通り、Cloud9を使用したRuby on Railsの環境構築の手順を記載します。
独学でPHP・Laravelを学習しており、現在就活中なのでプロのエンジニアではありません。
転職希望の企業がRubyとRailsを使用した開発をメインとしているので、改めて学習が必要となりアウトプットも兼ねてカキコします。Cloud9を選択した理由は以下の通りです。
- 使用PCがwindows10のため、ローカルに入れるよりもLinux環境の方がエラーの際情報が多い
- ポートフォリオのインフラにAWSを使っている為アカウントを持っていた
- 基本無料で使用できる
なおこの記事は環境設定のハウツー的な構成ではなく、私が行った手順とエラーを時系列そのままで記載します。
「環境設定の方法を知りてえんだ!」って方はプロの記事を参考にしてください。目標
AWSのCloud9にRuby on Railsをインストールし、アプリケーションを起動して「Yay! You’re on Rails!」を表示させる
環境
Amazon linux
ruby 2.6.3
Rails 6.0.3.4
MySQL 5.5.62(後々5.7にバージョン上げてエラーになる)
MySQL 5.5から5.7へのバージョンアップと、libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解消やってきましょう
バージョン確認
とりあえずRubyのバージョン確認。もともとインストールはされている模様。
$ ruby -v ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-linux]続いてRailsのバージョンも確認しておきましょう。
$ rails -v Rails 5.0.0Railsも入っているんですね。
でもバージョン5.0.0って、beta1が2015年12月18日にリリースされたらしくかなり古い様子。
バージョンアップしたいなあ。$ gem install rails $ rails -v Rails 6.0.3.4取り合えず最新版にアップデートできました。
そうしたらプロジェクトを作成するディレクトリを作ります。
名前は何でもいいので、ホームディレクトリに移動して"rails-training"を作成します。
そのあとcdコマンドでrails-trainingディレクトリに入り込みましょう。$ cd $ mkdir rails-training $ cd rails-trainingここでMySQLのバージョン確認を思い出す。
$ mysql -v ERROR 2002 (HY000): Can't connect to local MySQL server through socket'/var/lib/mysql/mysql.sock' (2)エラーが出ました。
どうやらsocketファイルが無いのでMySQLに接続できていないらしい。MySQLを再起動すると自動でsocketファイルが作成されるので、一度停止してもう一度起動してみる。
(restartでもいいけど、何となく気持ち悪いのでしっかり停止と起動を実行)$ /etc/init.d/mysqld stop $ /etc/init.d/mysqld start touch: cannot touch ‘/var/log/mysqld.log’: Permission denied chown: changing ownership of ‘/var/log/mysqld.log’: Operation not permitted ~略~ chown: changing ownership of ‘/var/lib/mysql’: Operation not permittedパーミッションエラーですね、私には起動させる権限がないようです。
$ sudo /etc/init.d/mysqld startってことでsuduコマンドで強制実行。うまく再起動できました。
引き続き以下のコマンドで最低限のセキュリティ設定をします。MySQLの初期設定についてメモしておく
その後に忘れずMySQLの再起動。$ mysql_secure_installation ~略(対話形式でパスワード等を設定)~ $ sudo /etc/init.d/mysqld restartプロジェクト作成
ここまでやってやっとRaylsプロジェクトを作成。
カレントディレクトリが先ほど作ったrails-trainingであることを確認します。RailsはデフォルトのデータベースがSQLiteに設定されているので、オプションで"-d mysql"を指定してあげます。
$ rails new training_app -d mysql ~略~ An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling. ~略~こんなエラーが発生しました。
「rails new」コマンドを実行すると、アプリ生成時に必要なパッケージを「RubyGems」で自動的にインストールする仕組みになっています。
さきほど、「-d mysql」オプションを指定したことにより、「gem install mysql2」コマンドが内部で実行されました。
ところが、「mysql2」というgemパッケージをインストールするには、「mysql-devel」というrpmパッケージがCentOSにインストールされていることが前提となっていたため、「mysql2」のインストールに失敗してしまったようです。
つまり、この問題を解決するにはyumで「mysql-devel」をインストール
gemで「mysql2」をインストールという手順を踏む必要があります。
【Ruby on Rails環境構築】インストールから起動までの手順【MySQL】という事なので、私はyumで「mysql-devel」をインストールしました。
加えて引用サイトに記載もありますが、先ほどの"rails new"コマンドは生きているので、プロジェクト自体はすでに作成されています。
ですので新しく"rails new"コマンドを実行する必要はありません。$ sudo yum install -y mysql-devel $ ls app bin config config.ru db Gemfile lib log package.json public Rakefile README.md storage test tmp vendorサーバー起動
プロジェクトディレクトリに移動してから実行します。
$ cd training_app $ rails s => Booting Puma => Rails 6.0.3.4 application starting in development => Run `rails server --help` for more startup options Exiting Traceback (most recent call last): ~略~ /home/ec2-user/.rvm/gems/ruby-2.6.3/gems/webpacker-4.3.0/lib/webpacker/configuration.rb:95:in `rescue in load': Webpacker configuration file not found /home/ec2-user/rails-training/training_app/config/webpacker.yml. Please run rails webpacker:install Error: No such file or directory @ rb_sysopen - /home/ec2-user/rails-training/training_app/config/webpacker.yml (RuntimeError)rails webpacker:installを実行してくださいエラー:そのようなファイルまたはディレクトリはありません
ひとまず言われた通りに"rails webpacker:install"を実行。
$ rails webpacker:install Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/yarnがインストールされていないようなので、インストールしてから再度実行し、サーバーも起動。
$ brew install yarn $ rails webpacker:install $ rails sページにアクセスすると、以下のエラーが出て正常に表示されない。
To allow requests to **********.vfs.cloud9.ap-northeast-1.amazonaws.com, add the following to your environment configuration:
なにやらRails6からDNS再バインド攻撃対策として、自身からしかアクセスができない仕様になっているらしい。
config/application.rbのApplicationクラスにアクセスを許可する設定を記載すれば解決される様子。
<config/application.rb> require_relative 'boot' require 'rails/all' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) module TrainingApp class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 6.0 #以下一文を追加。末尾が"amazonaws.com"のドメインは許可する。 config.hosts << ".amazonaws.com" # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. end endこれで表示されることを信じてサーバーを起動。
$ rails sMysql2::Error::ConnectionError
Access denied for user 'root'@'localhost' (using password: NO)今度はMySQLのrootユーザーのパスワードが一致しないので、データベースにアクセスできないときた。
これはLaravelでも経験があるエラーなので落ち着いて対処。Raylsではtraning_app/config/detabase.ymlにデータベース周りの設定を記載すればいいみたい。
私の環境だと17行にさっき対話形式で設定したMySQLのパスワードを書いていく。<traning_app/config/detabase.yml> ~略~ default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: ここにパスワードを記載 socket: /var/lib/mysql/mysql.sock development: <<: *default database: training_app_development ~略~これでどうでしょうか、そろそろ勘弁してください。
$ rails sActiveRecord::NoDatabaseError
Unknown database 'training_app_development'また出ました。
"training_app_development"なんてデータベース知りませんっておっしゃってます。あれ?そもそもデータベース作ってないな。
ってことでデータベースを作ります。$ mysql -u root -p Enter password: > CREATE DATABASE test_table; > show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test_table | +--------------------+よしよし、データベースはできました。
後から知りましたが、Railsはdbコマンドでデータベースを作成した方がいいようです。$ rake db:create
この作った"test_table"を使用するように設定します。
ひとつ前でパスワードを設定した"traning_app/config/detabase.yml"ファイルを眺めていると、エラー内容と同じ名前のデータベース名を発見。
多分ここに書けば反映されそう。<traning_app/config/detabase.yml> ~略~ default: &default adapter: mysql2 encoding: utf8mb4 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: ここにパスワードを記載 socket: /var/lib/mysql/mysql.sock development: <<: *default database: ここにデータベース名を記載 ~略~これで完璧なはず。
$ rails s**********.vfs.cloud9.ap-northeast-1.amazonaws.com で接続が拒否されました。
調べてみると画像の部分を押して別タブで開けば表示されるとの情報を発見。
出来ました。
Yay! You’re on Rails!を表示できたので、とりあえず一件落着です。MySQLのバージョンアップは以下の記事を参照。
MySQL 5.5から5.7へのバージョンアップと、libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解消
- 投稿日:2020-11-26T09:04:21+09:00
[Rails]ユーザー新規登録時にメールを自動配信する機能を実装する[備忘録]
はじめに
先日、Ruby on Railsでアプリケーションを作成しました。
その中で、ユーザーに新規登録をしてもらうと同時に、ユーザーのメールアドレス宛にメールを送る機能を作りました。
ネットで調べつつ、試行錯誤しながら実装したのですが、色々な情報が入り乱れていて、少しだけ分かりにくかった印象があったので、備忘録も兼ねて、ここでまとめたいと思います。
それでは参りましょう!メール送信機能を記述
config/environment/development.rb#以下を追記 config.action_mailer.raise_delivery_errors = true config.action_mailer.default_url_options = { :host => 'localhost:3000'} config.action_mailer.delivery_method = :smtp config.action_mailer.smtp_settings = { :address => 'smtp.gmail.com', :port => 587, :domain => 'gmail.com', :user_name => "hoge@gmail.com", # user_name, passwordはご自身のものに変更して下さい。 :password => "hogehoge", :authentication => :plain, :enable_starttls_auto => true }メーラーを作成
メール送信におけるコントローラー的役割を果たすMailerを作成します。
rails g mailer <メーラー名> <メソッド名>
ターミナル$ rails g mailer ThanxMailer complete_registrationこのコマンドを打つことにより、
app/mailers/application_mailer.rb
とapp/mailers/thanx_mailer.rb
が生成されます。
次に、それらのテンプレートファイルを編集していきましょう!!メーラーを編集
app/mailers/application_mailer.rbclass ApplicationMailer < ActionMailer::Base default from: '管理者' layout 'mailer' endapp/mailers/thanx_mailer.rbclass ThanksMailer < ApplicationMailer def complete_registration(user) @user = user mail(:subject => "登録ありがとう!!!!", to: user.email) end endメール本文の作成
views/thanx_mailer/complete_registration.text.erb<%= @user.name %> 様 会員登録ありがとう!!!!コントローラへの記述
app/controllers/users_controller.rbdef create @user = User.new(user_params) if @user.save ThanxMailer.complete_registration(@user).deliver end endメーラーは、
メーラー名.メソッド名
と記述することで、クラスメソッドを呼び出すように実行できます。
実際の送信はdeliver
メソッドが行います。おわりに
メール送信機能自体は、記述する量も比較的少ないため、理解がしやすいと思います。
ただただコピペするだけでなく、一つ一つの意味をしっかり理解していきたいですね。
- 投稿日:2020-11-26T09:00:20+09:00
Formオブジェクトについて
Formオブジェクトとは?
1つのフォーム送信で複数のモデルを操作したい場合や、テーブルに情報を保存しない情報に対するバリデーションを行いたい場合使うデザインパターンのこと。
実装手順
① 新たにformオブジェクト用のmedelを作成する
ターミナル% rails g model モデル名② form_withメソッドに対する機能とバリデーションを行う機能を持たせる。
test_form.rbclass TestForm include ActiveModel::Model◯ include ActiveModel::Model
この記述のように、ActiveModel::Modelをincludeすることで、form_withやrenderなどのヘルパーメソッドの引数として扱えたり、バリデーションの機能が使用できるようになる。
この記述は「Formオブジェクト」を呼ばれる。③ 保存したい複数のテーブルのカラム名全てを属性値として扱えるようにする。
test_form.rbclass TestForm include ActiveModel::Model attr_accessor :カラム名1, :カラム名2, ・・・◯attr_accessor
ゲッターとセッターを定義してくれるメソッド。与えられた引数をもとに属性を設定し、これを取得するメソッド(ゲッター)と更新するメソッド(セッター)を定義することができる。
モデルに対応するテーブルのカラム名以外の属性を扱いたい場合は、attr_accessorを用いて追加する。④ バリデーションを設定する。
test_form.rbclass TestForm include ActiveModel::Model attr_accessor :カラム名1, :カラム名2, ・・・ validates :カラム名1, 各オプション validates :カラム名2, 各オプション or with_options 各オプション do validates :カラム名1 valitates :カラム名2 end◯with_options
同じオプションがある場合は、with_optionsを使用することで、validatesをまとめることができる。formオブジェクトで使用するモデルのバリデーションは、各モデルにバリデーションを記述するのではなく、formオブジェクトに記述する。
理由としては、バリデーションが引っかかった場合に、各モデルにバリデーションを記述していると、引っかかった理由をうまく画面に表示できなくなるため。⑤ データをテーブルに保存する処理を書く。
test_form.rbclass TestForm include ActiveModel::Model attr_accessor :カラム名1, :カラム名2, ・・・ validates :カラム名1, 各オプション validates :カラム名2, 各オプション or with_options 各オプション do validates :カラム名1 valitates :カラム名2 end def save 変数 = 外部のモデル名.create(カラム名1: 保存したい値, カラム名2: 保存したい値, ・・・) モデル名1.create(カラム名1: 保存したい値, カラム名2: 保存したい値, ・・・, カラム名: 変数.id) モデル名2.create(カラム名1: 保存したい値, カラム名2: 保存したい値, ・・・, カラム名: 変数.id) ) end保存したい複数のモデルに外部モデルに関するidを保存したい場合は、変数に外部モデルの情報を代入して、その変数のidを保存したいモデルに記述する。
- 投稿日:2020-11-26T08:43:21+09:00
Mysql2::Error: Table '○○_production.users' doesn't existを解消した話
表題が発生し、解消するまでの顛末をまとめました。原因は2つありました。
開発環境
ruby 2.6.5
Rails 6.0.3.2
capistrano 3.14.1
AWS EC2
webサーバーNginx
アプリケーションサーバーUnicorn事の発端
データベース関連の修正を行ったため、本番環境(EC2)で一度テーブルを落としてから再作成しました。
そしてマイグレーションを行った際、表題のエラーが発生しました。結論、原因は2つありました。原因その1 userを参照するreferencesメソッドが、userテーブルが作成される前に読み込まれていた
こちらの方がわかりやすくまとめられてます。
https://obel.hatenablog.jp/entry/20170719/1500456452rails db:migrate:statusで確認すると、確かにテーブルのステータスがdownになっていました。
タイトルの通り、エラーメッセージの指摘は何ら矛盾がありませんでしたね。
ただ、開発環境ではエラーにはならず?アプリも正常に動いていたので、気づくのにかなり時間を費やしました。こちらの記事の通り、マイグレーションファイルの日付を修正して、読み込まれる順序を変更しました。
そして、statusはupになりましたが、それでもエラー自体は解消されませんでした。原因その2 本番環境でgit pull origin masterをしていなかった
結論、これによって上の作業がEC2上に反映され、ようやく解消に至りました。
いやもう思い違いをしていたというか、今なお十分な理解に至っていないのですが、githubへpush(作業ブランチで開発していた場合はmergeしてmasterへpullまで)したら、このコマンドは必要ないと思っていました。
実際、それで自動デプロイのコマンドを打てば、本番環境に機能を実装させることはできていました。git pull origin masterは毎回必要なのだろうか?この辺りは宿題になっています。
git,githubは大分慣れたように思っていましたが、まだまだ知識が不足しているようです。
- 投稿日:2020-11-26T02:00:29+09:00
Rails 6.0~ DEPRECATION WARNINGが出力されないようにした。
rails6.0~から定数の読み込みにzeitwerkモードというものが使われるようになりました。
https://railsguides.jp/autoloading_and_reloading_constants.html
それに起因して、サーバーを起動した際に以下のようなwarningがログに出力されるようになりました。
このwarning邪魔なので消したいなあと思っていたところ、無事解決することができたので、同じことで困っている方たちのお役に立てれば良いなと思い、雑記します。DEPRECATION WARNING: Initialization autoloaded the constants MyClass.結論から述べると、このwarningが出る原因は、initializersディレクトリ内で自分で定義した定数(MyClass)を読み込んでいたことでした。
initializersディレクトリ内での定数の読み込みはリロード時には行われない。そして、自分で定義した定数はリロード時に変更を反映できる方が開発の便宜上良いので、initializersで読み込むべきではない、といったところでしょうか。