Rails + PostgreSQLでカラムをキャストできない型に変更する方法
トラブル時の状況
- bit_varying型のカラムをinteger型に変更したかったがCAST()で雑にキャストできなかった
- 一旦string型に変更してからinteger型に変更しようとするマイグレーションを実行したが、string型で処理されてしまった
解決方法
カラムを削除する変更と追加する変更を行う
マイグレーションファイル
class ChangeUserHogehogeToInteger < ActiveRecord::Migration[5.2] def change remove_column :user, :hogehoge add_column :user, :hogehoge, :integer, null: false, comment: "hoge" end end
カラムの変更後に必要な作業
- モデルテストの修正
- モデルのバリデーション修正
おまけ
- integerに変更後、負数を許さない場合はモデルでバリデーションチェックを行う
validates :hogehoge, presence: true, numericality: { greater_than_or_equal_to: 0 }
参考
この記事はkb Advent Calendar 2020 3日目の記事です。
『SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ』を読んで
感想
スクラムマスターのあるべき精神が完結にまとめられた本です。
ページ数もそれほど多くなく、説明も端的でわかりやすいので読みやすかったです。
こんな人におすすめ
スクラムガイドを読んでスクラムの概要は理解できたものの、スクラムマスターとしてどう振る舞えばいいのかわからない人。
以下、印象に残った部分
心理状態モデル
全部なるはやで問題解決してチームを作業に戻したい衝動に抵抗できれば、「自己組織化したチームを作る」という目標に大きく近づきます。
僕が初めてスクラムマスターをやったとき、問題が発生するとすぐに割って入って答えを言っていました。
やがて、チームが次に何か問題に直面したとき、僕の指示を仰ぐようになりました。良くないことだったと反省しています。
たとえ最強のアジャイルコーチでも、1人で組織を変えることはできません。成功には、自己組織化したチームが必要です。ですから、スクラムマスターたちで構成されるチームを作るのが最良の出発点になります。
スクラムをやろうとしても経営に近いところにいる役職者の理解を得ることが難しいと日頃感じています。
たとえ正しいことでも1人でプレゼンなどの啓蒙活動をしていても、正論を押し付けるだけのようになってしまい、あまりいい反応が得られませんでした。
そのような状況でも志を共にする仲間がいれば力強いですね。
システム全体を俯瞰する。細かいプロセスにはこだわらずに何が課題かを考える。
コミットメントに苦労しているというチームをよく見かけますが、解決すべき課題はより低レベルの信頼の欠如にあるものです。
仕事では、KPTをやっているものの、あまり深堀りせずTryを考えようとするのでいつも対処療法になります。
議論を深めて根本原因を取り除こうとせず、議論を避けて無駄な作業を減らそうとしない雰囲気がチームを取り巻いているように感じています。
中には、チームにとって受け入れるのが簡単ではないプラクティスもありました。スタンドアップミーティングなどです。そのため、回数を減らすか、全部やめようとしています。
耳が痛いです…。プロダクトバックログリファインメントはちょくちょくスキップされます。
守破離の「守」でスクラムを体に染み込ませないまま、型を崩してはいけませんよね。
まとめ
内容は認定スクラムマスター(CSM)研修で学んだことと齟齬は無く、翻訳も丁寧で読みやすかったです。
読んで満足するのではなく、カイゼンに繋がるような動きができるよう、頑張らなくてはならないですね。
SCRUMMASTER THE BOOK 優れたスクラムマスターになるための極意――メタスキル、学習、心理、リーダーシップ
Railsチュートリアルで作成したサンプルアプリをDockerで動かす手順
雑に備忘録
基本的な内容は下記ページに書かれているもので、それをRailsチュートリアルで作成したサンプルアプリ向けにまとめました。
docs.docker.com
ローカルPCで動かす想定です。
以下、コマンドとファイルの記載内容
nano Dockerfile
FROM ruby:2.5 RUN apt-get update -qq && apt-get install -y nodejs postgresql-client RUN mkdir /sample-app WORKDIR /sample-app COPY Gemfile /sample-app/Gemfile COPY Gemfile.lock /sample-app/Gemfile.lock RUN bundle install COPY . /sample-app # Add a script to be executed every time the container starts. COPY entrypoint.sh /usr/bin/ RUN chmod +x /usr/bin/entrypoint.sh ENTRYPOINT ["entrypoint.sh"] EXPOSE 3000 # Start the main process. CMD ["rails", "server", "-b", "0.0.0.0"]
※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。
nano Gemfile
source 'https://rubygems.org' gem 'rails', '~>5'
touch Gemfile.lock
nano entrypoint.sh
#!/bin/bash set -e # Remove a potentially pre-existing server.pid for Rails. rm -f /myapp/tmp/pids/server.pid # Then exec the container's main process (what's set as CMD in the Dockerfile). exec "$@"
nano docker-compose.yml
version: '3' services: db: image: postgres volumes: - ./tmp/db:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password web: build: . command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/sample-app ports: - "3000:3000" depends_on: - db
※Dockerサイトのテンプレートから「Myapp」を「sample-app」に置き換えています。
リポジトリのクローン
git clone [リポジトリのURL]
リポジトリのファイルを移動
cd sample_app mv * ../ mv .git ../ mv .gitignore ../ cd .. rm -rf sample_app
イメージ作成
docker-compose build
データベース作成
docker-compose run web rake db:create
データベースのマイグレーション
docker-compose run web rake db:migrate
サンプルデータの反映
docker-compose run web rake db:seed
アプリケーションのコンテナ起動
docker-compose up
完了
余談
Postgresqlのコンテナ起動してもRails側でDBの設定変えないとデフォルトのSQLite使っちゃいます。
Dockerfile、docker-compose.yml、entrypoint.sh、Gemfile.lockはリポジトリに入れておくと便利です。
AWSでEC2インスタンスを最小構成で作成する手順
最小構成でWebサーバー用のEC2インスタンスを立ち上げる手順をメモしておきます。
後述する書籍の内容を参考に、チェックシート的な使い方ができるようにしました。
目標
VPC、サブネット、EC2インスタンスそれぞれ一つずつ作成し、EC2インスタンスにSSHでログインする。
手順
- VPCを作成する
「名前タグ」は自由、「IPv4 CIDR ブロック」は「10.0.0.0/16」 - サブネットを作成する
「名前タグ」は自由、「VPC」は1で作成したもの、「アベイラビリティーゾーン」は自由、「IPv4 CIDR ブロック」は「10.0.1.0/24」 - インターネットゲートウェイを作成する
「名前タグ」は自由 - インターネットゲートウェイをVPCにアタッチする
3で作成したインターネットゲートウェイを選択した状態で、「アクション」→「VPCにアタッチ」→「使用可能な VPC」に1で作成したVPCを選択して「インターネットゲートウェイのアタッチ」 - ルートテーブルを作成
「名前タグ」は自由、「VPC」は1で作成したもの - ルートテーブルにサブネットを関連付ける
5で作成したルートテーブルを選択して、画面中央部にある「サブネットの関連付け」タブを選択した状態で「サブネットの関連付けの編集」
2で作成したサブネットがリストに表示されていることを確認して選択し「保存」 - ルートテーブルにインターネットゲートウェイのルートを追加する
5で作成したルートテーブルを選択して、画面中央部にある「ルート」タブを選択した状態で「ルートの編集」
「送信先」は「0.0.0.0/0」、ターゲットは3で作成したインターネットゲートウェイを選択 - EC2インスタンスの作成
「ネットワーク」は1で作成したVPC、「サブネット」は2で作成したもの、「自動割り当てパブリック IP」は「サブネット設定を使用(有効)」を選択
「ネットワークインターフェース」の「プライマリIP」に「10.0.1.10」を入力
「セキュリティグループの設定」で「新しいセキュリティグループを作成する」を選択、「SSH」(初期状態で設定済み)と「HTTP」のようなWebアプリへアクセスするためのルールを設定
他の項目は自由
秘密鍵を忘れずにダウンロードする - ローカルPCからSSHログインできるか確認する
ssh -i [秘密鍵のパス] ec2-user@[EC2インスタンスのIPアドレス]
参考書籍
丁寧な説明で分かりやすくおすすめです。
余談
「6.ルートテーブルにサブネットを関連付ける」を忘れがち
GitLabをhttpsでアクセスするように設定した後はGitLab APIのオプションにverifyを追加する
仕事で使っているGitLabをhttpsに設定したときにバックアップに使っているスクリプトを変更し忘れたので自戒を込めて書きます。
Pythonで確認
元にしたコードは下記の以前書いた記事に記載しています。
learning-mind.hatenablog.com
def get_all_user_email_dict(): headers = { 'Private-Token': os.environ['ACCESS_TOKEN'], } params = ( ('page', '1'), ('per_page', '1000'), ) response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt") data = response.json() path_dict = dict() for row in data: username = json.dumps(row["username"], indent=4).replace("\"", "") path_dict[username] = json.dumps(row["email"], indent=4).replace("\"", "") return path_dict
下記の部分を修正しました。
response = requests.get('https://XXXXX/api/v4/users', headers=headers, params=params, verify="ca.crt")
verify="ca.crt"
の"ca.crt"
はクライアント証明書のファイル名です。
verify
のパラメータはFalse
でも処理は進みますが、警告が表示されます。
コマンドで確認
元にしたコマンドは↓ learning-mind.hatenablog.com
curl --cacert ca.crt --header "Private-Token: $ACCESS_TOKEN" https://XXXXX/api/v4/users | jq .projects[].path
URLおよびファイル名は環境に合わせてください。
--cacert ca.crt
が追加されています。
--cacert
はcurlのオプションで、ca.crt
はクライアント証明書のファイル名です。
感想
自分が書いた記事に助けられることは多い
『アマゾンのすごいルール』を読んで
どのような本か
アマゾンで敷かれているルールについて、著者である佐藤将之さんがアマゾン社員時代に経験したこと踏まえて説明されている本です。
内容は、2018年に出版されたということもあり、紹介されているルールはネットニュースでの話題になったことも多く、目新しいことは多くはありませんでした。
ただ、著者の経験したことは読んでいて状況がイメージしやすく、アマゾンのルールの本質を理解できました。
印象に残った箇所
AWSのサービス開始に至った経緯
アメリカの人たちはクリスマスに集中してものを買うそうです。
クリスマス商戦の商品を補充しておくための大規模な倉庫を保有しているのですが、クリスマス以外の時期は他の業者に貸しています。
それと同様の発想で、クリスマス時期の大量アクセスに耐えきる程のサーバーを閑散期に貸し出すAWSが生まれたそうです。
AWSを知ったときは「先見の明があるなあ」くらいにしか思っていませんでしたが、倉庫の例を知ることで、AWSは生まれるべくして生まれたと思えました。
「在庫なし」の商品ページへのアクセス数をチェックしている
アマゾンはロングテール戦略をとっていて、めったに売れない商品、所謂「死に筋商品」も商品が無くならない限り商品ページを載せ続けます。
その戦略をとるに至ったのは、「在庫なし」の商品ページへのアクセス数をチェックしていたからということでした。
欲しい商品の在庫が無い状態が続いているなら何回もアクセスしてみるといいかもしれませんね。(笑)
移動サーバールーム
ある時、大企業のデータをAWSに移行するとき、遅い転送速度をフォローするために、トラックに積んだサーバーに太い光ファイバーを使ってデータを移して運んだそうです。
これはアマゾンがスピードを重視しているという方針から行ったそうです。
ドラマ『シリコンバレー』でも、経緯は全く違いますがサーバーをトラックで運ぶというエピソードがありましたね。
もしかしたらアマゾンのエピソードが元ネタになっているのかも知れません。
全体的に、読んでいると著者のアマゾンに対する強い愛が伝わってくる文章でした。
PCの再起動時にplymouthが止まってGitLabが起動しなかった件
困った……
仕事で使っているGitLabのサーバーPCを再起動した後、いつも通りブラウザでページを開こうとするとエラー画面が表示されました。
サーバーにSSHで入って状態を見ると、GitLabとそれに関わるプロセスが起動していませんでした。
設定は、システム起動時に自動的に起動するようにしていたにも関わらず起動できないとはむむむ……。
とりあえずGitLabの起動コマンドを打ってみたものの失敗しました。
gitlab-ctl start
下記記事と現象は同じでした。
writesnow.net
$ sudo gitlab-ctl start fail: alertmanager: runsv not running fail: gitaly: runsv not running fail: gitlab-monitor: runsv not running fail: gitlab-workhorse: runsv not running fail: logrotate: runsv not running fail: nginx: runsv not running fail: node-exporter: runsv not running fail: postgres-exporter: runsv not running fail: postgresql: runsv not running fail: prometheus: runsv not running fail: redis: runsv not running fail: redis-exporter: runsv not running fail: registry: runsv not running fail: sidekiq: runsv not running fail: unicorn: runsv not running
上記ページには解決策も書かれていますが、僕の環境では下記コマンドを実行しても反応が無いという状況でした。
systemctl start gitlab-runsvdir
その他、Rubyのバージョンを確認したりもしましたが、僕が使っていたGitLabはOmnibus packageでインストールしたので関係ありませんでした。
結論
plymouth-quit-waitが動き続けていたため他のプロセスが起動できなかったことが原因でした。
(GitLab依存の問題ではありませんでしたので、影響は他のアプリにもあったかもしれません)
原因の特定に至った過程
この現象についてGitLabの公式ページに書かれていました。
Since GitLab 11.2, the gitlab-runsvdir starts during the multi-user.target instead of basic.target. If you are having trouble starting this service after upgrading GitLab, you may need to check that your system has properly booted all the required services for multi-user.target via the command:
つまり、誰かがGitLabに必要なサービスの起動を妨げているようです。
公式ページに従って、妨げているサービスを確認します。
systemctl -t target
このとき、loaded inactive dead
となっているサービスが二つありました。
(抜粋)
graphical.target loaded inactive dead start Graphical Interface multi-user.target loaded inactive dead start Multi-User System
この二つが原因のようです。
前述の公式ページに書かれている通り、次のコマンドでsystemdのキューを確認します。
systemctl list-jobs
結果(抜粋)
plymouth-quit-wait.service start running
plymouth-quit-wait
がrunning
のまま止まっていました。
plymouthとは
plymouthはシステム起動時および終了時のスプラッシュを表示するソフトだそうです。
調べると、下記ページのようにアンインストールすることで解決できると書かれていました。
しかし、業務で使用しているということもあり極力既存のモジュールをアンインストールしたくはありませんでした。
解決策
GUIモードで起動しようとして止まっているので、CUIモードに切り替えると解決しました。
systemctl isolate multi-user.target
念のためキューを確認します。
# systemctl list-jobs No jobs running.
# systemctl -t target
を実行するとrunning
のままのサービスはありませんでした。
感想
正直危なかった……。先輩に教えてもらえなかったら解決できてなかったかもしれません。感謝です。
そろそろLPICとか取った方がいいのかとも思いました。