RailsでNOT NULL制約をマイグレーションでつける

Railsで、NOT NULL制約がついてないカラムに後からマイグレーションでNOT NULL制約をつける時のやり方。

migrateファイルで、change_column_nullを使う。DEFAULTも設定する場合はさらにchange_column_defaultも行う必要がある。

class ExampleMigration < ActiveRecord::Migration[6.0]
  def change
    change_column_null :table, :column, false, true
    change_column_default :table, :column, from: nil, to: true
  end
end

change_column を使うと PG::NotNullViolation: ERROR: column "column" contains null values の様に、すでにレコードが作成されていた場合はエラーになってしまう。change_column_nullを使うとNULLのカラムをデフォルト値(4パラ目)でUPDATEしてからNOT NULL制約をつけてくれる。

Railsで特定のコントローラーでセッションを使わないようにする

Railsはコントローラーで session に書き込みを行うとセッションIDがアサインされ、Set-CookieでCookieにセッションIDが設定される。

デフォルトでは全てのリクエストでCSRFトークンをセッションに格納しているため、何も設定していないとランディングページなどのセッションをあまり必要としない静的ページへのアクセスでセッションストアの容量が圧迫されたりしてしまう。

コントローラーで protect_against_forgery? をオーバーライドして false を返すようにすると、session に書き込みが行われないため、新規にセッションIDがアサインされなくなる。

class StaticPagesController < ApplicationController
  skip_before_action :authenticate_user!

  parivate

  def protect_against_forgery?
    false
  end
end

ただし当然ながらCSRFトークンが作成されなくなるため、使いどころは注意されたし。

外部サービスで使用しているPostgresqlのデータベースをHeroku Postgresにリストアする

基本的にはHerokuのドキュメントに全て書いてある。
https://devcenter.heroku.com/articles/heroku-postgres-backups

今回はAWS EC2のRailsアプリケーションをHerokuに移行した時のデータベースのコピーしたので、手順をメモしておく。

AWSサービス側での操作

  1. メンテナンス画面にした後、冗長化してあるWEBサーバーを止めて1台のシングル構成に。
  2. パブリックディレクトリ(Herokuがアクセスできる場所)にPostgresqlのダンプファイルを作成する。念のため、ファイル名は乱数にでもしておく。
PGPASSWORD=$PG_PASSWORD pg_dump -Fc --no-acl --no-owner -U $PG_USER -h $PG_HOST -p $PG_PORT $PG_DATABASE -f /var/www/app/current/public/xxxxxxxxxx.dump

Heroku側での操作

heroku pg:backups:restore 'https://www.app.com/xxxxxxxxxx.dump' DATABASE_URL --app=app-name --confirm=app-name

これでHerokuにDBがコピーされるので、ドメインをHerokuに向けてメンテナンスを解除する。

注意

heroku pg:backups:restore を実行すると、URLにアクセスできなかったなどの理由でリストアに失敗した場合でもHeroku Postgres のデータベースは削除されてしまう。

System spec で CSRFトークンが取得できない

症状

Rails6 の system spec で、Ajax での POST処理のテストを書いていたら、meta タグの csrf-token が取得できずにエラーとなった。

const csrfToken = document.querySelector('meta[name=csrf-token]').getAttribute('content');
// => Uncaught TypeError: Cannot read property 'getAttribute' of null

原因

そもそも RAILS_ENV=test の時は allow_orgery_protection が false に設定されているので csrf_meta_tags が何も出力しないようだった。

config/environments/test.rb で以下のようになっているところを true に変更したら csrf_meta_tags で meta タグが出力されるようになった。

  # Disable request forgery protection in test environment.
  config.action_controller.allow_forgery_protection = false

Math.floor を使っていると webpack の minify で Error: Couldn’t find intersection が発生する

症状

Rails5.2 で ./bin/webpack 実行時に Error: Couldn't find intersection というエラーが発生する。

再度 ./bin/webpack を実行すると発生しなくなる。 tmp/cache/webpacker を削除すると再現する。

キャッシュが無い状態で ./bin/webpack もしくは rails assets:precompile 時に発生するため、開発環境では2回目のコンパイルでうまくいくのでスルーしてしまい、CIやデプロイ時にエラーになってしまう。

assets:precompile の時はログに Compilation failed: とだけ出力されるので webpack のフェーズでのエラーだと気づくのに時間がかかってしまった。

原因

https://github.com/babel/minify/issues/904

.babelrc の presets から minify を外すと再現しなくなるため、こちらの issue の通り、minify に問題があるようだった。

2019/11 時点で issue は対応されておらず、問題が発生する条件はいくつかあるようだが、Math.floor を使っていると発生する、ということに心当たりがあった。

解決?(応急処置)

minify が呼び出しているbuiltIns というプラグインで Math.floor の変形をしている。

https://babeljs.io/docs/en/babel-plugin-minify-builtins

ひとまず、.babelrc の presets で minify の builtIns を無効にすることでエラーは発生しなくなった。

["minify", {"builtIns": false }]

トヨタ生産方式 脱規模の経営をめざして

トヨタ生産方式といえば「かんばん」という勝手なイメージでしたが、「かんばん」についての具体てきな話はほとんどなかった。

ジャスト・イン・タイムというやり方がどのようにできあがっていったのかという話。経営者と技術者それぞれのマインドが素晴らしいなと思った。

ザ・ゴールとリーダーズを見た後に読むとグッとくると思う。リーダーズではあまり描写されなかった不況に陥ってからの労働者側の働き方を勝手にイメージして感動できた。

国家

とても長い2500年くらい前の人たちの対談。ソクラテスの話に周りがうんうんと頷いて、いや、それちょっと話の持って行き方が強引じゃない?と思ったりして読んでいるとちゃんと誰かがそれに突っ込んで話が戻ったりしてどんどん話が長くなる。登場人物も話が長くなってしまうのを嫌がったりしている。哲学者たちはこうやって理論を積み上げていくんだなぁと思ったりした。

洞窟の比喩やイデア論の説明が所々出てくるけど、昔、教科書で習った真の三角形の例え話で自分が思っていたのとは何か違った。SF小説のフラットランドの世界だった。

Railsコンソールで手っ取り早くバリデーションの動作確認をするワンライナー

->(c, k, v) { c.new(k => v).tap(&:valid?).errors[k] }.call(User, :email, "text@example.com")

ポイント

  • tap内 で valid? を実行することでメソッドチェーンで errors が呼び出せる。
  • ラムダ式を使って変数がコードの後ろに来るようにしてあるので、コンソール内で値を変えながら何度も動かしてみるのが楽。

Atomic Design ~堅牢で使いやすいUIを効率良く設計する

やっぱり Atomic Design は良い考え方だけどスペルが難しくて日本人には辛いなぁと言う印象 😇

Atomic Design 自体は以前から知っていて、学び直しのつもりで読んだのだけど、Storybookの使い方が紹介されていたのが棚からぼた餅で良かった。

コンポーネントをディレクトリにして Component/index.js, Component/stroy.js, Component/style.js, Component.test.js などをまとめるやり方は、Component.js, Component.story.js, Component.style.js, Component.test.js としていくよりファイルの見通しは良くなるんだけど、エディタのタブのファイル名が全部 index.js になってしまい、「あれ、今どこの index.js 触ってるんだっけ?」「あのコンポーネントの index.js どれだ?」って迷子になりやすいのが玉に瑕だと思っている。

請求書より入金額が少ない時の帳簿の付け方

個人事業主で freee で帳簿をつけていて、相手型のミスで請求書より少ない金額が入金され、翌月に前月の不足額を加算した金額で入金された時の帳簿の付け方。

  • 売上高は請求書通りにする
  • 前月の不足額を事業主貸にする
  • 翌月の超過額を仮受金にする