fluid_27’s blog

勉強した内容をアウトプットするためのブログ

railsのenumを初めて使ってみた

ハッカソンで共同開発している、

「電車の混雑具合をユーザーに投稿してもらって、混雑具合を即時的に反映させていく」

というアプリの中で、メンバーの一人がenumを使っていて、「何それ?」ってなったので、enumについて調べてみた。

 

 

enumとは

DBに保存する定数を複数個設定できるもの。

 

例えばユーザーから混雑具合を選択してもらう際、

viewで

<%= form_with model: @post, local: true do |f| %>

<%= f.select :congestion_level, Post.congestion_levels.keys.map {|k| [k, k]}, {prompt:"混雑具合を選択してください"}, class: 'form-control' %>

<% end %>

 

というようにselectを使ってユーザー選択にさせ、DBに保存する際に enum を使って定数を設定していれば、受け取った値(key)に対応する値(value)をDBに保存することができる。

 

 

enumの設定

以下のようにenumを使用する際はモデルにkeyとDBに保存するvalueを指定。

 

Post.rb

enum congestion_level: { "着席できる" => 1, "座れないが立って乗れる" => 2, "座席の前で立てる" => 3, "立っているのがやっと" => 4, "乗り切れないほど混雑している" => 5 }

 

上記の例でいうと、

"着席できる" がviewで選択された際にはDBには 1 という数値が保存される。

"座れないが立って乗れる" が選択された際には 2 が保存される。

といった具合になる。

 

 

enumを使う上でのポイント

  • 保存するカラムはboolernかinteger型のどちらかである必要がある
  • 設定していた定数以外は保存できない(それ以外は弾いてくれる)
  • モデルに保存するためのkeyとvalueを設定する

 

 

引っかかったポイント

 当初、viewの記述が

<%= form_with model: @post, local: true do |f| %>

<%= f.select :congestion_level, Post.congestion_levels,  {prompt:"混雑具合を選択してください"}, class: 'form-control' %>

<% end %>

となっていた為にエラーが発生していた。

 

本来なら

  • viewから  "着席できる" などenumで設定していたkeyが送られる→ 保存する際に key: "着席できる" に対応する value: 1 が保存

という流れが正しいのに対し、

  • viewから  1 などの数値が送られる→  key: 1 に対応する valueがない → エラー

となっていた。

 

参考サイト

https://pikawaka.com/rails/enum

を参考に

viewで選択する値をenumで設定したkeyになるようにしたところエラーは解消された。

アプリに枠を埋め込んで、その枠自体をスクロールできるように

日本語が下手でうまく説明できませんが、下記図のようにページ自体でなく、ページの中に表示した「投稿一覧」や「誓約文」とかだけを枠で囲ってスクロールさせたかったので、やり方調べてみました。

 

f:id:fluid_27:20210530132417p:plain

 

参考サイト

https://techacademy.jp/magazine/25158

を参考にしました。

 

調べてみた

思ったより簡単で、cssでスクロールさせたい要素の親要素に

overflow: scroll ;

を付属すればいいだけみたいです。

 

実際にrailsのアプリで書いたコード

html.erb

<div class='card posts'>
<div class='card-body'>
<% @posts.each do |post| %>
<li class="list-group-item">
<div>名前:<%= post.user.name %></div>
<div><%= post.direction %>方面&ensp;
駅名:<%= post.station.station_name %>&ensp;
<%= post.time %>時頃</div>
<div>コメント:<%= post.comment %>&ensp;
混雑度:<%= post.congestion_level %></div>
</li>
<% end %>
</div>
</div>

 

scss

.posts{
height: 500px;
width: 500px;
overflow-y: scroll;
}

 

画面に投稿一覧を表示し、かつスクロールできるようにしました。

 

ちなみに

今回は上下スクロールしかつけませんでしたが、横スクロールつけるなら

overflow-x: scroll;

としたり、枠からはみ出す際はスクロールをつけず、はみ出た部分は表示させない。

などの設定もできるみたいです。

 

こんな簡単にできるとは思いませんでした(笑)

多分、また使うと思います。

HerokuでMySQLからPostgreSQLに変換する際に躓いたエラー

railsで開発していたアプリをherokuでデプロイすることにしました。

 

当初、アプリをherokuでデプロイする予定ではなかったので、DBはMySQLだったものを本番環境だけPostgreSQLに移行することにしました。(本当は悪手かもしれませんが、、)

その経緯をまとめたのが下記記事です。

 

fluid-27.hatenablog.com

 

今回はその際に躓いたエラーと解消までの道のりです。

 

herokuで

$ rails db:migrate

した際に

rails aborted! StandardError: An error has occurred, this and all later migrations canceled: PG::DatatypeMismatch: ERROR: column "business_time" cannot be cast automatically to type text HINT: You might need to specify "USING business_time::text". : ALTER TABLE "shops" ALTER COLUMN "business_time" TYPE text[]

というエラー発生。

 

アプリ開発段階でカラムの1つに「文字列の配列」をデータ型に選択したことがありました。

途中でそのカラムは削除し、通常の「文字列」に変更したのですが、

migrationファイルに

db/migrate/20210205024357_change_datetype_business_time_of_shops.rb 

 class ChangeDatetypeBusinessTimeOfShops < ActiveRecord::Migration[5.2]

  def change

   change_column :shops, :business_time, :text, array: true

  end

 end

というファイルが残ってしまっていた為に、postgresqlに変換する際エラーが発生しているようでした。(開発段階では後に上記カラムを削除するmigrationファイルを追加してますが、postgresqlでは上記migrationファイルを読み込んだ時点でエラーとなり、rollbackしてしまっているようでした)

 

色々、ググってみて、migrationファイルをdownした状態で削除→rails db:migrateする方法を取りました。

 

該当migrationファイルだけdownさせればいい話だと思うのですが、当時はいまいち事態を把握できておらず、ローカル環境で

$ rails db:migrate reset

してから該当ファイルを削除した後、githubに反映させるつもりでした。

が、下記エラーが

rails aborted!

ActiveRecord::NoEnvironmentInSchemaError:

Environment data not found in the schema. To resolve this issue, run:

bin/rails db:environment:set RAILS_ENV=development

 

上記のエラー文に従って下記実行

$ bin/rails db:environment:set RAILS_ENV=development

 

改めて

$ rails db:migrate reset

問題なく実行できたので、問題のあったmigrationファイルを削除しました。

その後、githubにプッシュしたものの、何故か反映されませんでした。

 

ので、github上で直接問題のあったファイルを削除し、改めてherokuコンソールでrails db:migrateすることで解決しました。

dockerを初めて使ったので、コマンド等まとめてみた

前々からDockerも勉強しないとなぁ。くらいに思っていたが、ついにハッカソンの共同開発でDockerを使う日が来たので、kindle unlimitedをフル活用し、Dockerの本を数冊読んだので、備忘録がてら、あくまでザックリとまとめてみる。

 

 

Dockerについてざっくりと

 

Dockerとは

「コンテナ型のアプリケーション実行環境」で、いわゆる「仮想化技術」の一種。

「コンテナ」と言う単位でOSをマルっと動かしており、カーネルはホストのOSと共有する。

 

Dockerイメージとは

「コンテナ」を作るための雛形が「Dockerイメージ」

 

Dockerfileとは

「 Dockerfile」は「Dockerイメージを作るための元ネタ」。

 

Dockerコンテナを生成する流れ

Dockerfileをビルドすると「Dockerイメージ」が出来上がる。

Dockerイメージを実行すると「コンテナ(Dockerコンテナ)」が生成される。

 

コンテナの状態

コンテナには

  • 実行中
  • 停止
  • 破棄

という3つの形態がある。

 

停止状態から再び起動することはできるが、破棄されたコンテナは復元することができない。

 

 

 

Dockerコマンドまとめ

 

Docker-composeコマンド

$ docker-compose ps

コンテナ一覧表示

up は起動中

exit は停止

 

$ docker-compose up

プロジェクト内の全てのコンテナを起動

 

$ docker-compose down

プロジェクト内の全てのコンテナを停止

 

$ docker-compose exec コンテナ コマンド

対象のコンテナで対象のコマンドを実行する。 

ex)

$ docker-compose exec web bash

とすると中でLinux操作が行えるようになる。

 

 

Dockerコンテナのコマンド

コンテナのコマンドは基本的に

docker container 操作 オプション

という書式。

 

  •  run

Dockerイメージからコンテナを生成するためのコマンド。

構文:docker container run オプション イメージ名:タグ名

 

オプション;

--name

コンテナ名を定義。

 

-i と-t

-i と-tをつけると

「Ctrl+C」のような操作をコンテナが受け付けるようになる。セットで使う必要があり、"it"と書くこともできる。

 

-d

コンテナをバックグラウンドで動かすためのオプション。Webサーバなどの用途でコンテナを動かす場合に使う。

 

-p

ポートフォワードをするためのコマンド。例えば「p9999:8080」とすると、9999ポートのアクセスを8080ポートにフォワードする。

 

  • ls

ローカルPCに保存されているコンテナを一覧表示するためのコマンドです。

ex)

docker container ls

 

  • stop

コンテナを停止するためのコマンド。

構文:docker container stop コンテナ名

 

  • restart

コンテナを再実行するためのコマンド。

構文:docker container restart コンテナ名

  

  • rm

ローカルPCに保存されているコンテナを削除するためのコマンド。

構文:docker container rm コンテナ名

  

  • prune

停止中のコンテナをまとめて削除するためのコマンド

 

 

 

Dockerイメージのコマンド

  • build

Dockerfileから Dockerイメージをビルドするためのコマンド。

 

構文:docker image build -t イメージ名:タグ名 Dockerfileのパス

ex)

docker image build -t helloworld:1.0 .

 

-tオプションはタグを指定するオプション。

最後の . はDockerfileがカレンとフォルダにDockerfileがある。ということ。

 

--pullオプションを使用すると、DockerfileのFROMに指定されているイメージを毎回「Docker Hub」から取得する場合に"true"を明示する。

ex)

docker image build --pull=true -t helloworld:1.0 .

 

  • ls

ローカルPCに保存されている Dockerイメージを一覧表示するためのコマンド。

ex)

docker image ls

 

-aオプションを付与すると、すでに無効状態になっているDockerイメージも表示対象となる。

 

  • pull

Docker Hubで提供されているDockerイメージをダウンロードするためのコマンド。

構文:docker image pull イメージ名:タグ名

 

  • rm

ローカルPCに保存されているDockerイメージを削除するためのコマンド。

構文:docker image rm イメージ名

 

コンフリクトが起きた場合、

-fオプションをつけると、コンフリクトした関連のあるものも全て削除する。

 

  • prune

不要なDockerイメージをまとめて削除するためのコマンド。

 

 

Dockerfileのコマンド 

  • FROM

Dockerイメージのベースとなるイメージを指定。

ここで指定したイメージは「Docker Hub」というホスティングサービスからダウンロードされる。

また、イメージ名に続いて「:タグ」を記述できる。タグを指定しなかった場合、latestという最新版のタグとみなされる。

ex)

FROM ubuntu:14.04

 

  • RUN

Dockerイメージをビルドする際に、「コンテナの中で実行するコマンド」を指定する。

命令の引数には実行するコマンドをそのまま指定する。

ex)

RUN echo 'Hello!!'

 

  •  COPY

ローカルPCのリソースをコンテナにコピーする。

構文:COPY コピーするリソース コピー先のパス

ex)

COPY main.rb /tmp/work/

 

  • CMD

コンテナの実行時に「コンテナ起動時の最初の1回だけ実行するプロセス」を指定。

実際に実行するコマンドを空白で区切って、それぞれ1つを「引数」として[ ]の中に順に記述する。

ex)

CMD ["go", "run", "/hello/main.go"]

上記の場合、go run/hello/main.goとしてコンテナないで実行される。

  

  • EXPOSE

コンテナを外部公開する際のポートを指定する。

 

 

Heroku CLIをインストールしてデプロイした道のりとDBをMySQLからPostgreSQLに変えてみる

 

目標:Herokuでデプロイする

 

環境:

mac Catalina 10.15.7

ruby 2.7.3

rails 2.5.2

テキストエディタ Visual studio code 1.56.2

 

前提:

herokuにアカウントは作成してある。

gitにレポジトリは作成しており、リモートレポジトリを繋いでいる。

 

道のり:

1. rails newで新しいアプリ作成

2. postgresqlをgemに追加し、bundle install

group :production do

  gem 'pg'

end

をgemに加え、$ bundle install の実行

 

3.  herokuのCLIインストール

$ brew tap heroku/brew && brew install heroku

でインストールできるらしい。

 

が、自分は以前に入れていたらしく

$ heroku --version

とすると、

dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.67.dylib
Referenced from: /usr/local/bin/node
Reason: image not found
zsh: abort heroku --version

と出てきた。

 

ググってみて、以下に行き着いた。

railsでローカルアクセスした時にエラーになる(node) - ムーのしょ〜もない様でしょ〜もなくもないブログ

 

要は、nodeをインストールした際に icu4cというのを含めてインストールしてしまい、元々macに入っていたlibicucore.dylib というライブラリと干渉してしまったらしい。

 

$ brew reinstall node

の実行で解決。

 

4. herokuにログイン

$ heroku login --interactive

 

5.  herokuにSSH接続できるようにする

$ heroku keys:add

 

6.  herokuにアプリの作成場所を作る

$ heroku create

 

7. heroku にデプロイ

$ git push heroku master

 

以上。

 

感想:AWSにデプロイするより全然簡単だった。

 

追記:MySQLからPostgreSQLに変更してみる。

元々herokuでデプロイするつもりで作成していなかったアプリをherokuでデプロイすることにしたので、DBをMySQLからpostgreSQLに変更する必要がでた。

実際はかなり悪手なのかもしれないが、今回はherokuの公式ドキュメントにもその方法が載っていたので、手順にしたがって変更してみる。

https://devcenter.heroku.com/articles/heroku-mysql

 

1. MySQLのアドオンをプロビジョニングする

$ heroku apps

herokuに登録しているアプリ一覧が見れる。

 

$ heroku addons:create cleardb:ignite --app アプリ名

cleardbのアドオンをプロビジョニングする。

※cleardbを使用するにはクレジットカードの登録が必要。一定量までは課金なしで使用できる。

 

 

2. HerokuPostgreSQLに変更する

 

PostgreSQLをローカルで実行する

PostgreSQLをローカルで実行している時にDBに接続できるように、環境変数を設定する。

$ export DATABASE_URL=postgresql://$(whoami)

 

上記コマンドのDATABASE~以降のURLは下記コマンドで確認できる。

 

$ heroku config --app アプリ名

アプリに設定している環境変数などを取得できる。

=== アプリ名 Config Vars

DATABASE_URL:             postgres://dfevijm...(略)

LANG:                     en_US.UTF-8

RACK_ENV:                 production

RAILS_ENV:                production

RAILS_LOG_TO_STDOUT:      enabled

RAILS_SERVE_STATIC_FILES: enabled

SECRET_KEY_BASE:          4b573c0563ad3...(略)

 

PCにpostgresqlをインストール

調べたところ、自分のPCにはすでに入っていた見たいなので、飛ばしました。

必要なら下記サイトを参考にすれば大丈夫だと思います。

Postgres.app – the easiest way to get started with PostgreSQL on the Mac

※ちなみに、 $ which psql

で表示されるパスがPostgresql.appディレクトリ の中ではなかったので、上記サイトの3番だけ行いました。

 

3. pgloaderのインストール

インストール

https://github.com/dimitri/pgloader/blob/master/README.md

を参考にインストールします。

$ brew install --HEAD pgloader

 

自分はmacなので上記コマンドを実行。

 

 

4. データの移行

Postgresqlデータベースを作成し、CLIを使用してMySQLデータを移行する。

$ createdb pgdbname

$ pgloader mysql://username:password@localhost/mysqldbname postgresql:///pgdbname

 

 

初学者なので、間違い等あれば指摘していただけると助かります。

あくまで備忘録として書きました。次回、行う際もブログを見返しながらも、公式ドキュメントも確認しつつ行おうと思います。

AWSのIAMについてのまとめ

 

IAMポリシーとは

Identity and Access Managementの略

ユーザー管理、アクセス権限を設定するもの。

 

 

IAMポリシーは

  • 管理ポリシー
  • インラインポリシー

に分類することができる。

 

また、管理ポリシーは

  • AWS管理ポリシー
  • カスタマー管理ポリシー

に分類することができる。

 

 

つまり、

IAMポリシーを分類すると

  • 管理ポリシー

   -AWS管理ポリシー

   -カスタマー管理ポリシー

  • インラインポリシー

こんな感じに分類できる。

 

 

 

「管理ポリシー」と「インラインポリシー」の違いについて

・管理ポリシー

スタンドアロン型。ポリシー単体として存在できて、複数のプリンシパルエンティティにつけたり外したりできる。

 

・インラインポリシー

埋め込み型。「ポリシー」単体では存在できず、プリンシパルエンティティと1対1の関係にある。

 

プリンシパルエンティティとは

AWSでは

  • IAMユーザー
  • IAMグループ
  • IAMロール

の3つのこと。

通常、管理ポリシーを使うことが推奨されている。

 

使い分け

たとえば、ポリシー内のアクセス権限が意図したプリンシパルエンティティ以外のエンティティに間違って割り当てられないようにする必要がある場合など、ポリシーとプリンシパルエンティティで厳密な1対1の関係を維持する必要がある場合に便利。

 

 

 

続いて

AWS管理ポリシー」と「カスタマー管理ポリシー」の違いについて

 

AWS管理ポリシー 

予めAWSによって用意されている管理ポリシー。大まかに各AWSサービスごとにフル権限と読み取り権限が用意されている。

 

・カスタマー管理ポリシー 

利用者が独自に作成する管理ポリシー。ジェネレータで作成するか手書きで作成する。

 

 

使い分け

どこまで細かく権限設定したいか。によって変わってくる。

元々用意されている設定で事足りるのであれば、「AWS管理ポリシー」を。

より細かく設定したいのであれば「カスタマー管理ポリシー」を選択。

 

ちなみに、

AWS管理ポリシーは

・EC2すべてに対して何でも操作可能

・S3バケットすべてに対して読み取りだけ可能

 

カスタマー管理ポリシーは

・特定のタグがついたEC2に対して、起動停止だけ可能

・特定のS3バケットに対してPUTのみ可能

 

 

 

参考サイト

https://www.simpline.co.jp/recruit/blog/tech_ty/aws%E7%AE%A1%E7%90%86%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%A8%E3%82%A4%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E9%81%95%E3%81%84%E3%81%8C%E5%88%86/

ウェブサイトに接続できない時に試すこと

AWSのEC2インスタンス 立てたサーバーにアクセスできなくて、様々な本やサイトで読んでエラーが起きている問題の切り分け方法をザックリまとめてみました。

まだネットワークの知識が浅いので、随時更新していこうと思います。

 

 

 1. クライアント側のネットワーク環境に問題ないか確認する

(指定のサイト以外は閲覧できるか。など)

 

 2. ホスト名が解決できるか確認

nslookupコマンドやdigコマンドを利用

DNS解決できなければ、DNS設定もしくはDNSサーバ自体に問題がある可能性。

 

nsloogupの使い方:

nslookupは、DNSサーバーに問い合わせができるコマンド。

$ nslookup で対話モードに。

対話モードに入ったら、

ドメイン名を入れたらIPアドレスが。

IPアドレスを入れたらドメイン名が表示される。

対話モードで「?」を入力すると全オプションを見れる。

 

$ nslookup

>yahoo.co.jp

  ipアドレスが表示される。

>183.79.135.206

   ドメイン名のyahoo.co.jpが表示される。

>?

   全オプションを表示

 

 

 3. pingコマンドでネトワークの疎通を調査する

pingコマンドが通らなかった場合、途中のネットワークに問題があるかwebサーバがダウンしている可能性が。ただし、ICMPが許可されてないとpingコマンドは使えない。

 

pingの使い方:

$ ping ドメイン名またはIPアドレス

Ctrl + cで停止する。

 

 4. telnetコマンドでポート80番に接続する

telnetコマンドでHTTPのウェルノウンポート番号の80番に接続。

→応答がなければポート80番がセキュリティの設定などによって閉じられている。もしくはApacheなどのHTTPサーバーのプロセスが起動していない、という事が考えられる。

 

telnetの使い方:

$ telnet IPアドレス [ポート番号]

 

 

 5. 上記の全てを確認して、それでもwebサイトに接続できない時は、アプリケーション内部の問題だと考えられる。

 

 

<追記>

curlコマンド

様々なプロトコルを使用してデータ転送を行うことができるコマンド。

 

HTTPのGETやPOST、HTTOSやFTPTelnetSMTPIMAPPOP3など様々な通信プロトコルをサポートしている。

 

最近の端末には最初から入っていて、ターミナルですぐにcurlコマンドを使用できる状態だが、入っていない場合はインストールする必要がある。

 

$ curl --version

でちゃんとバージョン確認できれば入っている。

 

curlコマンドの使い方:

$ curl (ドメイン名 or IPアドレス)

でそのURLの情報を取得できる。

 

ポート番号指定

$ curl (ドメイン名 or IPアドレス):ポート番号

 

オプション:メソッド変更

$ curl -X (リクエストメソッド) (ドメイン名 or IPアドレス)

例) $ curl -X GET https://www.yahoo.co.jp/

 

curl についての参考サイト

https://qiita.com/akane_kato/items/34b408336f4ec372b139

 

 

netstat

主にTCPの通信状態を調査するコマンド。

通信の状態や通信相手、通信しているプロセス、通信量などの情報を知ることができる。

 

netstatの使い方: 

$ netstat

現在アクティブなTCPコネクションの状態が表示される

 

状態

Listening 待受状態。

Established TCPコネクションが確立して通信している状態。

 

オプション

-a 全ての接続を表示

-n ホスト名/IPアドレス等を解決せずに数字で表示

-r ルーティングテーブルを表示

-t tcpに限定する

-u udpに限定する

-i ネットワークインターフェースの情報を表示

-p PIDと各ソケットが属するプログラム名を表示

-l listenしてるもののみ表示

 

 

netstat に関する参考サイト

https://www.atmarkit.co.jp/ait/articles/0207/20/news003.html

https://made.livesense.co.jp/entry/2016/05/10/083000