20200818のRailsに関する記事は12件です。

【Rails 】マイグレーションファイルについて

マイグレーションファイルとは

マイグレーションファイルとはデータベースに加える変更内容を記載するファイルです。

基本のコマンド

command
# モデル作成
$ rails g model モデル名

# マイグレーションファイル作成コマンド
$ rails g migration クラス名

マイグレーションファイルはモデル作成時に作成されます。
マイグレーションファイル単体でクラス名を指定し作成することも可能です。
クラス名は「アクション+テーブル名」で作成するのがわかりやすくていいですね!
これで/db/migrate/タイムスタンプ_クラス名.rb というファイルが作れる。ここに、スキーマの変更点を記載しましょう!

テーブルの作成

command
$ rails g model モデル名 カラム名:データ型

モデル作成時にマイグレーションファイルに記載する内容を「カラム名:データ型」で指定します。

指定できるデータ型は下記の通りです。

  • string : 文字列
  • text : 長い文字列
  • integer : 整数
  • float : 浮動小数
  • decimal : 精度の高い小数
  • datetime : 日時
  • timestamp : タイムスタンプ
  • time : 時間
  • date : 日付
  • binary : バイナリデータ
  • boolean : Boolean

マイグレーションファイルをDBへ反映させる

command
# マイグレーションファイルの実行
$ rails db:migrate

このコマンドを実行するとDBへマイグレーションファイルの内容が反映される。

マイグレーションファイルのロールバック

command
# マイグレーションファイルをロールバックする
$ rails db:rollback

実行したマイグレーションファイルをロールバックする。

マイグレーションファイルの確認

command
# 実行したマイグレーションファイルの確認
$ rake db:migrate:status

このコマンドで実行したマイグレーションファイルの内容確認ができる。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

エラーが出た! ※インタラクティブリクエストのテンプレートはありません


Ruby on Railsを使ってアプリ実装の学習中、目的のページを表示させようとしたら、こんな画面が:sweat_smile:

error1.png

「Controller」と「index」という言葉がチラついていたので、VSCodeのルーティングとコントローラーとビューファイルの記述をチェック!コマンドパレットでCompare Active File With Clipboardツールを呼び出して、見本のコード比べてみたけど、異なる部分は見つからず…

いよいよメンターさんに質問しようと、VSCodeのスクショを取っていたら、ビューファイルのディレクトリがおかしいことに気づいた!正しい場所にビューファイルを作り直して、祈りながらページの更新ボタンをクリックすると、ロード時間が長い!「これはいけそう!」と思って待っていると、無事表示ができました:joy:



「〜のテンプレートがありません。」って出てきたら、ファイルの所在などをチェックしたら良いのかな?と少し学びました。

最後に問題のビューファイルの位置を作り直した時のスクショです。(正しい場所と間違った場所の両方あります。)

error2.png

間違っているのは3行目で、index.htnl.erbファイルがtweetsディレクトリに入ってなかったですね:sweat_smile:こんな初歩的な所で間違えるなんて…

でも、まあ、自分で解決できて良かったです:grin:
そして、きちんと表示された時、気持ち良かった:laughing:
ああ、こういった目に見える形で達成感をえられるのも、プログラミングの良さやな〜としみじみ思いました:blush:


※まだまだ、プログラミングを始めたばかりで、間違った解釈や記述をしてしまうことがあります。もし、お気づきのことがありましたら、どんどんアドバイス・ご指摘頂けたらと思います。最後まで読んで頂き、ありがとうございました!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud9でのHeroku操作

railsチュートリアルでherokuの操作をしきりに行うので、改めてCloud9でのHerokuの操作を整理しました。

前提

・Cloud9での操作であること
・Herokuに登録済みであること

【初回設定】

・クラウド上にHerokuをインストール

source <(curl -sL https://cdn.learnenough.com/heroku_install)

・インストールできたかの確認(バージョン確認)

heroku -v` or `heroku --version

・ログインとSSHキーの追加

heroku login --interactive #コマンド送信後mailアドレスとpasswordを入力する
heroku keys:add

・アプリを作成

heroku create #アプリ名は自動で決まる
or
heroku create (任意のアプリ名)
※ここで、表示されるURLがアプリのURLになる。
 remote:        https://********/ deployed to Heroku ⇦これがURL

デプロイ(変更を適用)

・gitに追加
git add (ファイル名 or 全て)

・gitにコミットする
git commit -m "コメント"

・herokuにpushする
git push heroku master

データベースに変更を適用する

・herokuにマイグレーションを実行する

 heroku run rails db:migrate

※自分はここがうまくいかなかったので以下で説明されているコマンドを実行しました。
https://qiita.com/bdogrep/items/8620dbba5e4c3fd859df
ありがとうございます。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

RailsをAWS ECS(Fargate)でホストする環境構築のすべて【3. ECSへのデプロイ、SSMによる接続】

前記事

RailsをAWS ECS(Fargate)でホストする環境構築のすべて【2. Docker定義、ECRの設定】
https://qiita.com/polar_bear_tech/items/87f5795346d246a1e07c

ECRにコンテナイメージをプッシュするまでを書きました。
今回はECS周辺の設定を行い、デプロイします。
加えて、SSMを使用した操作も行います。

下準備

ECS用セキュリティグループの作成

ECS用のセキュリティグループを作成します。
インバウンドはALBから80ポートと、VPC endpointを介してSSMからの接続のため443ポートを開けています。
スクリーンショット 2020-08-18 21.00.58.png

タスク実行ロールの作成

IAM>ロール>ロールの作成から、タスク実行用のロールを作成していきます。

ECSTask用のユースケースを選択して次へ。
スクリーンショット 2020-08-18 19.01.11.png

スクリーンショット 2020-08-18 19.01.30.png

ECSのタスクを制御するのと、SSMによる操作を行うため、以下のポリシーをアタッチします。

  • AmazonECSTaskExecutionRolePolicy
  • AmazonSSMManagedInstanceCore
  • AmazonSSMAutomationRole
  • AmazonSSMDirectoryServiceAccess

スクリーンショット 2020-08-18 19.01.51.png

スクリーンショット 2020-08-18 19.02.50.png

"ecsTaskExecutionRole"みたいな名前を付けて保存します。

SSMアクティベーションコードの発行

System Manager>ハイブリッドアクティベーションから、アクティベーションの作成を行います。
スクリーンショット 2020-08-18 19.23.14.png

説明と、管理できるインスタンス数(30くらいあれば良いかと思います)、有効期限を入力して作成。
スクリーンショット 2020-08-18 19.24.02.png

作成したら、画面上部にアクティベーションコードとIDが表示されるので控えておいてください。
控え忘れた場合は、もう一度作成すれば大丈夫です。
スクリーンショット 2020-08-18 19.24.10.png

ECSタスク定義

ECS>タスク定義から、新しいタスク定義の作成を押下し、作成していきます。

起動タイプはFargateを選択。
スクリーンショット 2020-08-18 19.04.38.png

タスク定義名を入力。
スクリーンショット 2020-08-18 19.08.01.png

タスク実行ロールに、先ほど作成したタスクを設定。
タスクサイズは、EC2のmedium規模で設定しています。ここは任意のサイズです。
スクリーンショット 2020-08-18 19.08.28.png

コンテナの追加ボタンから、ECRにプッシュしたコンテナイメージを追加していきます。
まずはnginxから、イメージ欄にはECRの一覧画面に表示されているURIをコピーして貼り付けます。
メモリ制限を4GiB、CPUユニット数を1024(1vCPU)に設定します。
スクリーンショット 2020-08-18 19.10.15.png

次はrailsコンテナを追加します。
nginx同様にURIをペーストし、メモリ制限を4GiB、CPUユニット数を1024(1vCPU)に設定します。
起動時に実行するシェル(エントリポイント)もコマンドをカンマ区切りで記載。
スクリーンショット 2020-08-18 19.15.51.png
スクリーンショット 2020-08-18 19.17.06.png

環境変数を設定します。
スクリーンショット 2020-08-18 19.25.08.png

ここで、先ほど取得したSSMのアクティベーションコード・IDを下記の変数名でそれぞれ設定します。

  • SSM_ACTIVATION_CODE
  • SSM_ACTIVATION_ID

その他、必要に応じて下記を設定します。

database.ymlで環境変数からロードするようにしておく値

  • DATABASE_HOST
  • DATABASE_PORT
  • DATABASE_USER
  • DATABASE_PASSWORD

image.png

AWSのAPIアクセス用のキー情報

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY

最後にスタートアップ依存順序をnginxのコンテナ側に追加します。
スクリーンショット 2020-08-18 19.26.24.png

コンテナを追加できたらこんな感じになります。
スクリーンショット 2020-08-18 19.27.02.png

以降は初期値のままで、作成まで進めます。

ECSクラスタ作成

ECS>クラスターからクラスターの作成を押下して、作成していきます。

テンプレートはFargate用の「ネットワーキングのみ」を選択。
スクリーンショット 2020-08-18 19.27.51.png

クラスター名を入力し、
CloudWatchでハードウェア監視を行いたい場合はCloudWatch Container Insightsにチェックします。
スクリーンショット 2020-08-18 19.28.51.png

作成したら、クラスターの管理画面になります。
スクリーンショット 2020-08-18 19.29.10.png

ECSサービス定義

最後!クラスター管理画面のサービスタブにある作成ボタンから、作成していきます。

起動タイプはFargate、タスク定義に先ほど作成したタスク定義を選択します。
リビジョンはlatestを選択。
タスク定義はバージョン管理されているので、これを更新したら最新を選んだり、前のリビジョンに戻したりできます。
サービス名を任意の内容で入力。
スクリーンショット 2020-08-18 19.29.54.png

タスク数は2とかにするとバランシングしてくれます。任意の個数指定してください。
デプロイに関してはCodeDeployを使用する場合はB/Gにするなど、任意です。
スクリーンショット 2020-08-18 19.30.29.png

ネットワークは最初に作成しておいたVPCを選択。
サブネットもECSコンテナをのせる予定の2つのサブネットを設定。
セキュリティグループは1つ目の記事で作っておいた、ECS用のセキュリティグループを適用。
パブリックIDの自動割り当ては、有効。(有効じゃないとSSMで接続できなかった気がする)
スクリーンショット 2020-08-18 19.31.09.png

ロードバランサも作っておいたものを選択しましょう。
ロードバランス用のコンテナは、nginxのコンテナを選択し、ロードバランサーに追加ボタンを押します。
スクリーンショット 2020-08-18 19.31.37.png
スクリーンショット 2020-08-18 19.31.58.png

ターゲットグループ名を作っておいたもので選択すると、全部自動入力されるかと思います。
スクリーンショット 2020-08-18 19.32.13.png

サービスの検出オプションは有効にしておきます。
スクリーンショット 2020-08-18 19.32.42.png
スクリーンショット 2020-08-18 19.32.53.png

オートスケーリングは任意で設定してください。
タスク平均のCPU・メモリの使用率や、タスクごとのリクエストの完了数を条件にしてオートスケーリングができます。
スクリーンショット 2020-08-18 19.32.59.png

作成して、タスクタブを開き、しばらくすると、RUNNINGになるかと思います!
スクリーンショット 2020-08-18 19.35.36.png

起動確認

EC2>ロードバランサーからDNS名をコピーして、ブラウザで確認しましょう。
スクリーンショット 2020-08-18 19.36.24.png

ルートはNginxのデフォルトを設定しているので、Nginxの初期画面がでました。
スクリーンショット 2020-08-18 19.37.06.png

SSMの操作

まだもうちょっとだけ。
System Manager>マネージドインスタンスを開くと、SSMで管理されているサーバが表示されます。
アクティベーションコードがうまく設定できていて、entrypoint.shでSSMのエージェントを起動できて、ネットワーク設定も開いていればオンラインとなっているハズです。
スクリーンショット 2020-08-18 19.37.38.png

選択し、アクションから「Start session」を押下すると、
スクリーンショット 2020-08-18 19.37.47.png

CUIが開きます。
Railsのコンテナに入れたので、これで操作可能なのですが、注意点として、ユーザーはssm-userというものになっています。
スクリーンショット 2020-08-18 19.38.36.png

sudoできるユーザーになっていますので、たとえばマイグレーションを行うとしたら、下記のコマンドで実行できます。

$ sudo -E bundle exec rake db:migrate RAILS_ENV=staging

ECSをSSMで管理する場合、課金対象になるかリファレンスから確実なところ読み取れなかったのですが、セッションマネージャでアクセスできるということは課金されると思います。
なので、使い終わったら登録解除しておくと、課金されませんので良いかも。
スクリーンショット 2020-08-18 19.43.06.png

最後に

入門できるまでが遠い門、まさにFargateでした。
こだわると、あとは下記が設定できると良いかと思います。

  • 環境変数はSystemManagerのパラメータストア使ったほうがいいです。
  • CodePipelineで自動デプロイ設定できます。
  • SSM接続のためのアクティベーションコード発行と環境変数への設定は、entrypoint.shでaws-cliつかってできたら手間が減る。

この記事としてはあくまで動作させるまでということで、以上です。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【独学】Railsチュートリアル終えた後の、ポートフォリオ(オリジナルアプリ)作成

はじめに

今回は

Railsチュートリアル学習したのに、ポートフォリオ(オリジナルアプリ)の作成に苦戦している方に向けて書いていこうと思います。

(スクールに通われている方にも参考になるかと思います。)

自己紹介

・24歳
・2020年3月 プログラミング学習開始
・6月 ポートフォリオ作成開始
 ポートフォリオ
 Github
・7月~現在 受託開発に取り組みながら、エンジニアへの転職活動をしています。

Railsチュートリアル学習したのにポートフォリオが作れない理由

それは、単純にRailsチュートリアルはポートフォリオ(オリジナルアプリ)を作り方を学べるものではないからです。

そもそも、RailsチュートリアルはRailsの構造を理解することに適した教材です。(おそらくスクール教材も)

実際に私自身もRailsチュートリアルを終えた後にすぐに、ポートフォリオ作成に取り組みましたがすぐに手が止まりました。

そこで、私が実践した3つのステップをご紹介します。

1. 転職活動している未経験者のポートフォリオを参考にする
2. とにかく作る
3. 現役のエンジニアにみてもらう

1. 転職活動している未経験者のポートフォリオを参考にする

転職活動しているほとんどの方がポートフォリオとGithubのリポジトリを公開しているので両方見ましょう。

コードが単純で書かれているものが多いので、Railsチュートリアルを十分に理解しているレベルなら、ほぼ理解できるかと思います。

ここでRailsチュートリアルで出てこない機能(gem)がたくさん出てくるので、Railsでどのような機能を実装できるのかがわかると思います。

私は、実際に検索機能(Ransack)ログイン機能(Devise)は他のポートフォリオを通じて知りました。

2. とにかく作る

簡単なものでもいいのでとにかく作りましょう!

私が最初に作ったサービスは「どのジムでどこの部位の筋トレをするかを投稿できるサービス」です。
正直、出来はひどいです。(見たい方は私のGithubから探してくださいw)

ですが、自分が理解していないところがわかったり、様々なエラーを自力で解決させたりすることは、実際に手を動かさないと経験できません。

一つポイントとして、作る前にモックアップを書きましょう!

なのでとりあえず作る!これに限ります。

3.現役のエンジニアにみてもらう

これが何よりも大事です!

「お前独学の人を対象に書いてるのに何いってんだ!」って言われても仕方ないですが、本当に現役のエンジニアにみてもらうのは大事なんです

2.であげた自分が理解していないところがわかったり、様々なエラーを自力で解決させたりすることは一人では限界がありますし、かなり時間がかかります。

冒頭で挙げたポートフォリオは独学で一人で作成しましたが、現役のエンジニアの方から頂いたフィードバックを元に修正をしたところ、カジュアル面談でかなり評価されたので、独学で頑張ってる方、初学者の方々には是非現役のエンジニアからレビューをもらいましょう!

私はオンラインサロンに入ってレビューをもらいましたが、Twitterなどに上げてみるのもいいですね!

最後に

本当に初学者のために書いたので、あまり参考になる人は少ないかもしれませんね汗

私自身、独学でやってた時に何から手をつけてわからなかったので、この記事を見て少しでも参考になれば幸いです!

次はポートフォリオ作りで技術的に苦労したところをあげようと考えてます!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

商品を売ったり買ったりする場合にclass_nameを使ってみた

はじめに

・商品を売ったり買ったりする場合のアソシエーションで悩みました。
class_nameオプションを使うことで解決できたので、備忘録として書きます。
・自分の状況に落とし込んでいるので、わかりにくかったらすみません。
・間違いなどあればご指摘いただけますと幸いです。

前提条件

・ユーザーがいます(usersテーブル)
・商品があります(itemsテーブル)
・商品が出品できる状況です(データ送信できる)
・1人のユーザーは複数の商品を出品(購入)することができます
・1つの商品は1人のユーザーに所属しています
→ユーザーと商品は1対多の関係です

class_nameって?

関連名を変更するために、クラス名を明示的に表示するオプションです。
たぶんどういう意味かあんまりわからないと思うので、具体例で説明します。

まず、以下のテーブルを見てください。
user has_many :items
item belongs_to :user
こんな関係性になってます。
・usersテーブル

id name
1 山田
2 田中
3 鈴木

・itemsテーブル

id name user_id 
1 イモ 1
2 サケ 1
3 フグ 2

山田さんはイモとサケを出品しています。
田中さんはフグを出品しています。

今、山田さんが出品したitemを全て取得することはできます。
イモを出品した人を取得することもできます。

ターミナルでコンソールを開いて1行ずつ入力してみてください
user = User.find(1)
user.items

でも、誰がイモを買うのか?
このままでは判断できません。

1つのitemに対して買う人が1人いる。
今はitemsテーブルのid = 1(イモ)を出品した人が山田ということしか取得できません。

買った人を取得するためには、出品した人と買った人を参照できるようにする必要があります。
つまり、外部キー制約のついたカラムを置く必要があります

・itemsテーブル

id name 外部キー1  外部キー2 
1 イモ 1 3
2 サケ 1 3
3 フグ 2 1

例えば、
外部キー1出品する人
外部キー2買う人
を持ってくればいいですね。

外部キー制約のカラムの認識は

「参照先のモデル名(小文字)」 + 「_id」
で認識されます。

わかりやすくするため、デフォルトの名前であるuser_idを使わないようにします。

・itemsテーブル

id name seller_id  buyer_id 
1 イモ 1 3
2 サケ 1 3
3 フグ 2 1

integer型seller_idカラムbuyer_idカラムを追加しましょう。

ただしこのままでは認識されません

UserモデルItemモデルのアソシエーションにforeign_keyオプションを使って、外部キーであることを明示的に宣言する必要があります。

ではこうしましょう

user.rb
class User < ActiveRecord::Base
  has_many :items, foreign_key: 'seller_id'
  has_many :items, foreign_key: 'buyer_id'
end
user.rb
class User < ActiveRecord::Base
  belongs_to :user, foreign_key: 'seller_id'
  belongs_to :user, foreign_key: 'buyer_id'
end

いつもはforeign_key: trueですけど今回は違います。
こういう名前にしたい!という名前をオプションで宣言します。
これで外部キーとして認識されました。

ですが、これではエラーになります

認識はされたものの、ユーザーに関連するitemsにアクセスする際、関連名が同一になっている(items)ため、出品したものを取得したいのか、買ったものを取得したいのかがわからないという状況になってしまっています。

→この状態でUserモデルのインスタンスに関連するitemsを取得しようとしてもエラーが出ます

エラーを解決するためにclass_nameオプションを使います

ここでclass_nameオプションが出てきます。

出品したものか、買ったものなのか、
あるいは
出品した人なのか、買った人なのか、
を判断するためにclass_nameオプションを使って、同一の関連名を変更します!!!
class ~ endまで丸ごと記述を追加してください。

user.rb
class User < ActiveRecord::Base
  # sold_itemsは出品された商品にアクセスする関連名、bought_itemsは買った商品にアクセスする関連名です
  # class_name: '関連するモデルのクラス名'
  has_many :sold_items, class_name: 'Item', foreign_key: 'seller_id'
  has_many :bought_items, class_name: 'Item', foreign_key: 'buyer_id'
end
item.rb
class User < ActiveRecord::Base
  # sellerは出品した人にアクセスする関連名、buyerは買った人にアクセスする関連名です
  belongs_to :seller, class_name: 'User', foreign_key: 'seller_id'
  belongs_to :buyer, class_name: 'User',foreign_key: 'buyer_id'
end

ということで、
usersテーブルのid: 1の山田が出品した商品と買った商品を取得することができるようになりました。

ターミナルでコンソールを開いて1行ずつ入力してみてください
user = User.find(1)
User.sold_items
User.bought_items

itemsテーブルのid: 1のイモを出品した人と買った人を取得することができるようになりました。

ターミナルでコンソールを開いて1行ずつ入力してみてください
item = Item.find(1)
Item.seller
Item.buyer

実際にミニアプリを作って試してみる時の注意点

・コントローラーへの記述でprivateメソッドの中にストロングパラメーターの記述をすると思いますが、出品者のidを取得する場合は.merge(seller_id: current_user.id)と記述すると良いかと思います。購入者の場合はseller_idをbuyer_idに変更すれば良いかと思います。

まとめ

・売る人と買う人がいる場合はclass_nameオプションを使うと実装しやすいと思います。
・ミニアプリを作る手順はこちらの記事を見てください。

参考

【Rails】アソシエーションを図解形式で徹底的に理解しよう!
https://pikawaka.com/rails/association#class_name%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3
Ruby on Rails アソシエーションの応用 class_name 【一つのモデルを複数に分岐する】
https://qiita.com/mylevel/items/421cc1cd2eb5b39e20ad

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

migrateのやり直し

migtateのやり直り方法

マイグレートしたファイルを削除する(やり直しをかける)

terminal
$ rails db:migrate:down VERSION=[time stamp]
$ rmi -rf [time stamp]_***.rb

終わり。

もし、downさせる前にマイグレーションファイルを削除してしまっていた場合、

設定等が残ってしまうのでその場合は、同じタイムスタンプのファイルを作成する必要がある

まずは、マイグレーションの状況を見て、何がup状態か確認する
やらかしている時は、下記のようなNO FILEがいる

terminal
$ rails db:migrate:status

Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200817055815  Devise create users
   up     20200817065100  Add name to users
   up     20200817102227  Create rooms
   up     20200817104106  Create entries
   up     20200818043808  ********** NO FILE **********

こうなっていた場合は、NO FILEのID(20200818043808)を元に、
簡易なマイグレーションファイルを作成する
(変にスペルミスしないように注意!、私は大文字小文字の打ち間違えで、エラー起こした。照り)

terminal
$ vim db/migrate/20200818043808_tmp.rb

class Tmp < ActiveRecord::Migration
    def change
    end
end

念のため、statusを叩いて、NO FILEがTmpに変わっていることを確認。(割愛)

terminal
$ rails db:migrate:status

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20200817055815  Devise create users
   up     20200817065100  Add name to users
   up     20200817102227  Create rooms
   up     20200817104106  Create entries
   up     20200818043808  Tmp

確認してできたら、上記の通りdownさせて、削除して終わり!

teminal
$ rails db:migrate:down VERSION=20200818043808
$ rm -rf 20200818043808_tmp.rb

終わり

参考にさせていただいた記事
https://qiita.com/gita/items/2198e2961a9fc7d10bd2

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EC2でRailsを起動する(手動デプロイ)

日記がてら。

EC2でのRails起動までの準備を着々と進めていき、
いざ起動コマンド!と思いきや

image.png

master failed to start, check stderr log for details
というエラー分が出て起動失敗。

stderrとはなんぞ?と思い調べてみるとconfig/unicorn.rbに
image.png
という部分が。
なるほどエラーログというものがあるのか。

lessコマンドを使用することでファイルの中身を除けるらしいのでターミナルで打ち込んでみることに。
すると
image.png
この青ラインが何度も出ていることに気づいた。

まずcredentialなるものについてファイルを覗くも、全く触ったことのないファイルだったので一旦後回し。
その上のaccess_key、secret_access_keyに何かありそうだ。
調べていくうちに起動までの手順を一つ抜かしていたようで、ターミナルにsudo vim /etc/environmentと打ち込み、
image.png
こちら2点を追記することであっさり解決。

ここまで調べたり試したりで所要時間3時間。

もしEC2でRails起動しないことでお悩みの方は上記の点の確認と、
・ローカル→GiuHubへのpushのし忘れはないか(mergeまで確認)
・GithubからEC2への反映(git pull origin master)のし忘れは無いか
・EC2サーバー側でエラーログの内容を確認し、原因を見つけたか
・カリキュラム通りの記載ができているか
・データベースは正しく起動しているか
・EC2サーバー側の環境変数は正しく設定できているか
・EC2インスタンスの再起動を行ってみる
を確認してみることをお勧めします。

またインスタンスの再起動は最初よくわからず全く別のインスタンスを作成したりとかしちゃったので、その場合はいらないインスタンスで右クリック→インスタンスの状態→終了で問題なく終わらせられます。
すぐには消えないけど24時間程度で消えるそうです。

誰かの参考になれば幸いです。

master failed to start, check stderr log for details
bundler: failed to load command: unicorn_rails
Aws::Sigv4::Errors::MissingCredentialsError: Cannot load Rails.config.active_storage.service:
missing credentials, provide credentials with one of the following options:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

OSがCatalina以降の環境構築

Command Line Toolsを用意

Command Line ToolsはWebアプリケーション開発に必要なソフトウェアをダウンロードするために必要な機能です。

ターミナルからCommand Line Toolsをインストール

ターミナル
$ xcode-select --install

出てくるポップアップには「インストール」→「同意する」→「完了」の順にクリック。

Homebrewを用意

Homebrewというソフトウェア管理ツールを導入します。

ターミナル
$ cd  # ホームディレクトリに移動
$ pwd  # ホームディレクトリにいるかどうか確認
$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"  # コマンドを実行

※処理に時間がかかる可能性のある操作

処理が進んでいくと、「press RETURN to continue or any other key to abort」(「続けるにはエンターキーを、やめるにはそれ以外の入力をしてください」)と表示されるので、ここではエンターキーを入力して先に進めましょう。

さらに、「password: :key2:」と表示されたら、PCのパスワードを入力してください。
ターミナル上でパスワードを入力しても文字は表示されませんが、間違いなく入力はされています。パスワードを入力し終わったらエンターキーを押してください。

その後、ダウンロードが完了し、再びコマンドを入力できるようになれば成功です。

Homebrewがインストールされているか確認

以下のコマンドを実行しましょう。

ターミナル
$ brew -v

Homebrewがインストールされているかを確認します。以下のように、Homebrewのバージョン情報が表示されれば無事にインストールされています。

ターミナル
$ brew -v
Homebrew 2.1.13

Homebrewをアップデート

ターミナル
$ brew update

Homebrewの権限を変更

ターミナル
$ sudo chown -R `whoami`:admin /usr/local/bin

rbenv と ruby-buildをインストール

ターミナル
$ brew install rbenv ruby-build

rbenvをどこからも使用できるようにする

ターミナル
$ echo 'eval "$(rbenv init -)"' >> ~/.zshrc

zshrcの変更を反映させる

$ source ~/.zshrc

readlineをinstallし、どこからも使用できるようにする

ターミナルのirb上で日本語入力を可能にする設定を行うために、以下のコマンドでインストールしましょう。

ターミナル
$ brew install readline
$ brew link readline --force

rbenvを利用してRubyをインストール

Webアプリケーション開発用のRubyをインストールします。以下のコマンドを実行しましょう。

ターミナル
$ RUBY_CONFIGURE_OPTS="--with-readline-dir=$(brew --prefix readline)"
$ rbenv install 2.5.1

※処理に10分程度かかる可能性のあるコマンドです。
2.5.1と書いてあるのは今回インストールするRubyのバージョンです。

利用するRubyのバージョンを指定

インストールしたRuby 2.5.1を使用するために、以下のコマンドを実行しましょう。

ターミナル
$ rbenv global 2.5.1

rbenvを読み込んで変更を反映させる

ターミナル
$ rbenv rehash

Rubyのバージョンを確認

ターミナル
$ ruby -v

Rubyのバージョンが、先ほどインストールした2.5.1であることが表示されれば完了です。

MySQLのインストール

MySQLは、Webアプリケーションにおけるデータを蓄積する場所のことです。

ターミナル
$ brew install mysql@5.6

※処理に時間のかかる可能性があるコマンドです。

MySQLの自動起動設定をする

MySQLは本来であればPC再起動のたびに起動し直す必要がありますが、それは面倒であるため、自動に起動するようにしておきましょう。

ターミナル
$ mkdir ~/Library/LaunchAgents 
$ ln -sfv /usr/local/opt/mysql\@5.6/*.plist ~/Library/LaunchAgents
$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql\@5.6.plist 

mysqlコマンドをどこからでも実行できるようにする

ターミナル
# mysqlのコマンドを実行できるようにする
$ echo 'export PATH="/usr/local/opt/mysql@5.6/bin:$PATH"' >> ~/.zshrc
$ source ~/.zshrc
# mysqlのコマンドが打てるか確認する
$ which mysql
# 以下のように表示されれば成功
/usr/local/opt/mysql@5.6/bin/mysql

mysqlを起動を確認

ターミナル
# mysqlの状態を確認するコマンドです
$ mysql.server status

# 以下のように表示されれば成功
 SUCCESS! MySQL running

Railsを用意

Rubyの拡張機能(gem)を管理するためのbundler(バンドラー)をインストールします。

ターミナル
$ gem install bundler

Railsをインストール

ターミナル
$ gem install rails --version='5.2.3'

rbenvを再読み込み

ターミナル
$ rbenv rehash

Railsが導入できたか確認

以下のコマンドを実行して、Rails 5.2.3が表示されれば問題なくインストールが完了しています。

ターミナル
$ rails -v

Node.jsを用意

Railsを動かすためにはnode.jsが必要となり、それをHomebrewを用いてインストールします。

Node.jsのインストール

ターミナル
$ brew install nodejs

この時、最後にError: node 13.10.0 is already installedと表示されても問題ありません。

Node.jsが導入できたか確認

以下のコマンドを実行して、v13.10.0のようにバージョンが表示されれば、問題なくインストールが完了しています。

ターミナル
$ node -v

以上でWebアプリケーション開発のための環境構築は完了です!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Rails]カラムを絞るだけの目的でselectメソッドは使うな!

ActiveRecordのselectメソッドについて

ActiveRecordでデータを取得すると基本的に該当するテーブルのすべての項目が取得されます。
発行するSQLを見ていただくと分かる通り、*で全項目取得しています。
全項目取得しているので、以降の処理ではどの項目でも参照することができます。

pry(main)> user = User.first
  User Load (0.7ms)  SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, name: "ham", created_at: "2020-03-10 01:03:37", updated_at: "2020-06-16 02:18:39">
pry(main)> user.id
=> 1
pry(main)> user.name
=> "ham"

ただ、全カラム使うわけではないので必要なカラムだけ取得したほうがいいのでは?という考え方もあると思います。
そんなときにselectというメソッドを使うことで取得するカラムを絞ることができます。
selectについて詳しくはRailsガイド をご覧ください。

selectを指定することで必要なカラムだけ取得することができます。
取得していないカラムは当然以降の処理では参照できません。

pry(main)> user = User.select(:id, :created_at).first
  User Load (0.7ms)  SELECT `users`.`id`, `users`.`created_at` FROM `users` ORDER BY `users`.`id` ASC LIMIT 1
=> #<User id: 1, created_at: "2020-03-10 01:03:37">
pry(main)> user.id
=> 1
pry(main)> user.name
ActiveModel::MissingAttributeError: missing attribute: name
from /usr/local/bundle/gems/activemodel-6.0.3.2/lib/active_model/attribute.rb:221:in `value'

カラムを絞るだけのselectは使うな!

あくまで私個人の考えではあるのですが、チーム開発など複数人で開発を行っている場合はカラムを絞るだけのselectは使わないほうがいいと考えています。

なぜなのか?

下記のコードを見てください。

def hoge(user_id)
  # selectでid, nameだけ取得
  user = User.select(:id, :name).find(user_id)

  ...(様々な処理)

  generate_response(user)
end

private

def generate_response(user)
  { id: user.id, name: user.name }
end

後にhogeメソッドのレスポンスにemailを追加することになったらどうでしょうか?
Userモデルはemailカラムを持っていることとします。

おそらく該当箇所を見つけて、generate_responseにemail足せばいいだけだな!
と思い、下記のように修正すると思います。

def generate_response(user)
-  { id: current_user.id, name: current_user.name }
+  { id: current_user.id, name: current_user.name, email: current_user.email }
end

よし修正終わり!1行で出来たぜ!!テスト実行!!!

pry(main)> { id: user.id, name: user.name, email: user.email }
ActiveModel::MissingAttributeError: missing attribute: email
from /usr/local/bundle/gems/activemodel-6.0.3.2/lib/active_model/attribute.rb:221:in `value'

あれ??動かないぞ・・・
受け取っているuserがおかしいのか?
たどってたどって、、、

そうです。selectで取得カラムを絞っているのでそちらにemailを足す必要があります。
下記も修正すれば動くようになります。

def hoge(user_id)
  # selectでid, nameだけ取得
-  user = User.select(:id, :name).find(user_id)
+  user = User.select(:id, :name, :email).find(user_id)

テストもうまくい通りました!

pry(main)> { id: user.id, name: user.name, email: user.email }
=> {:id=>1, :name=>"hoge", :email=>"hoge@example.com"}

どう思いますか?

RailsのActiveRecordを使うと基本全カラムを取得すると思うので上記のように一度はハマる人が多いと思います。

1回1回の手間はそこまでではないかもしれませんが、継続的に開発されていくシステムであれば毎回同じ事が起きます。
これは結構なコストです。また最悪の場合、気づかずにバグを生む可能性もあります。

今回のselectは開発コストやバグのリスクを上げてまで実装する必要があるのでしょうか?
私は多少最適ではなかったとしても他の人が勘違いしづらいコードのほうが良いと思っています。
これが私がカラムを絞るだけで使うselectは使わないほうが良いと思っている理由です。

selectの使いどころ

selectの存在を全否定している記事になってしまったのですが、もちろん使いどころもあります。
下記のように集計関数を使ったときです。

users_group_by_name = User.select('name, count(*) AS cnt').group(:name)
users_group_by_name.each do |u|
  p u.name
  # u.cntでカウントが取得できる
  p u.cnt
end

ただ、この場合も変数名をusersなどにしてしまうと勘違いさせてしまう可能性が高いので、それとわかる変数名にしたほうが良いでしょう。

あと、たまにjoinした先のテーブルをselectを使って直接アクセスできるようにしていることがありますが、これもとても分かりづらいのでやめたほうが良いと思います。

review = Review.select('reviews.id, users.name').joins(:user).find_by(id: 1)
# これでuser.nameにアクセスできる
review.name

普通にアソシエーション経由でアクセスするかdelegateを実装しておきましょう。

app/models/review.rb
review = Review.find_by(id: 1)
# アソシエーション経由でアクセス
review.user.name
# もしくはReviewモデルにdelegateを定義しておく (delegate :name, to: :user, prefix: true)
review.user_name

まとめ

この記事ではselectに焦点を当てましたが、複数人が同じコードを触るチーム開発では他人が理解しやすい(勘違いしづらい)コードを書くことが重要だと思います。
読みやすい(勘違いしづらい)コードを書くことで開発スピードが上がり、バグも減ると思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Herokuへのデプロイ(2回目以降の編集用)

この記事でわかること

①Herokuでapp作成し、後にローカルで編集した変更点をデプロイする方法。

:thinking:初めてappを作成する人用ではないので注意!

前提として

ディレクトリは作成中のappに移動した状態。
アプリはRailsで作成しています。
  
  
  
  
:hugging:ではここから初めて行きます:hugging:

コマンドの流れ

①Gemfileを変更したり追加したりしている場合バンドルインストール。
私はとにかく行っておきます。

% bundle install 

  
  
②変更のコミット

% git add .   
% git commit -m "Add pg gem for Heroku"                         

  
  
③リポジトリのプッシュをしてアプリのデプロイをする。

% git push heroku master 

  
  
④DBマイグレーションする。
本番環境Heroku用の作業だと思っている。

% heroku run rake db:migrate  

  
これでアプリを開いてみてください!
デプロイ出来ているはずです:v_tone1::crown:
  
お疲れ様でした!  
  
  
  

本記事は、まだまだ初学者のため自分用の記録です。
以下の記事を参考にさせていただきました。
参考記事( [Rails アプリを初めて Heroku にデプロイしてエラーとなったとき]https://qiita.com/hmmrjn/items/e2dff8036fbbd74f049a)
  
  
  

ひとことMemo

自分はですが、
デプロイ時③の工程で良くエラーが出てしまいました。
原因は「% bundle install 」の工程を忘れていたからでした。
  
  
本番環境へ写す際にGemfileを変更をしなければならないので起きていたようです。
  
  
  

  
最後まで読んで頂きありがとうござました!
ではまた!:blush::wave_tone1:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Rails】password_digestを生成する方法

password_digestについて

Railsでパスワードを保存する際にpassword_digestを使用することが多いと思います。Rails のモデル(フォーム)でパスワードを暗号化して保存する方法にある通り、パスワードを設定するときは、モデルを通してパスワードを設定すればpassword_digestを生成してくれる仕組みになっています。

やりたいこと

新規にユーザを作成するときはよいのですが、パスワードを更新するときに一度ユーザを取得した後に更新と言う手順が、モデルを通すと必要になります。これをユーザを取得せずにupdateだけ行いたい場合、password_digestを別途取得する必要があります。今回はその取得方法を紹介します。

対応方法

How to update user password using password_digest and form in Railsにある通り、BCryptを使用して直でpassword_digestの値を生成する方法が挙げられます。BCryptの詳細につきましてはこちらを参照ください。

サンプルソース

sample.rb
require 'bcrypt'

class Sample
  include BCrypt

  # password_digestの取得
  def self.get_password_digest(password)
    Password.create(password)
  end
end
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む