読者です 読者をやめる 読者になる 読者になる

newrelic が 422 エラーまで拾っているので400番台は拾わないようにしたい

newrelic Rails

direnv のログが毎回うざい件をなんとかする

Shell

公式でもまだ方針が定まってナサソウだけど、とりあえず export DIRENV_LOG_FORMAT= をzshrc に書いとけば黙ることがわかったので一旦これで。

Reference

tmux 2.3 にしたら "unknown key table: vi-copy" というエラーがでるようになった

tmux

tmux.conf にこういう設定を書いていたものが動かなくなった

## http://robots.thoughtbot.com/tmux-copy-paste-on-os-x-a-better-future
## Setup 'v' to begin selection as in Vim
bind-key -t vi-copy v begin-selection
bind-key -t vi-copy y copy-pipe "reattach-to-user-namespace pbcopy"

## Update default binding of `Enter` to also use copy-pipe
unbind -t vi-copy Enter
bind-key -t vi-copy Enter copy-pipe "reattach-to-user-namespace pbcopy"

原因は vi-copy というキーテーブルがなくなって、別名称に変わったため。
Fundamental change to how copy mode key bindings work: · tmux/tmux@76d6d36

既存の設定が使えなくなってるのでリプレース

bind-key -T copy-mode-vi y send -X copy-pipe "reattach-to-user-namespace pbcopy"
unbind -T copy-mode-vi Enter
bind-key -T copy-mode-vi Enter send -X copy-pipe "reattach-to-user-namespace pbcopy"

前はエスケープでviモード抜けられた気がするんだけど、できなくなってるような気もする。
とりあえず C-c で抜けられる。
モードを抜ける方法を含めてよく使いそうなのだけメモしておく

"bind -Tcopy-mode-vi C-c send -X cancel",
"bind -Tcopy-mode-vi C-j send -X copy-selection-and-cancel",
"bind -Tcopy-mode-vi Enter send -X copy-selection-and-cancel",
"bind -Tcopy-mode-vi Escape send -X clear-selection",
"bind -Tcopy-mode-vi Space send -X begin-selection",

date_validator gem を使ったバリデーションにおいてオプションで Date.current を指定する際に気をつけること

Rails

date_validator に限らず validations のオプションの指定の仕方に注意が必要なやつ。

何が問題か

Rails の validation のオプションで validates :birthday, date: {before_or_equal_to: Date.current} のような指定をしていて、 (要するに今日より未来の日付で誕生日の指定はさせない的な)問題が起きた。 この記述だと、サーバーが起動したタイミングで Date.current が固定されてしまうので、 サーバー起動日より後の日付で、当日を birthday に指定しようとすると、バリデーションエラーになってしまう。

対策

オプションは Proc オブジェクトで指定しておく。 つまり、バリデーションが走るタイミングで動的に評価されるようにしておく。

原因

lambda, -> がダメな理由 ダメなわけじゃなく、内部的な実装の問題 Procであれば本来的には問題ない

  • まず date: {before_or_equal_to: Date.current} のバリデーション自体が date_validator Gem の機能です
  • この部分の具体的な処理は vendor/bundle/gems/date_validator-0.8.1/lib/active_model/validations/date_validator.rb
  • def validate_each の中でオプションの分解を L.71 で開始
  • この時 Proc オブジェクトであれば .call で実行するのだけど、問題は .call(record) という形の呼び方なので  -> { Date.curret }  だと、引数の数チェックで引っかかってエラー -> (record) { Date.current } なら落ちない( record 使わないなら意味ないけど

Rails にJSONでリクエストを投げた際に発生する JSON::ParserError をハンドリングする

API Rails JSON Schema

何が問題か

API として公開している Rails Server に対して、Invalid な JSON データを送信した場合、 parse error が発生した場合は、適切にリダイレクトやエラーメッセージの制御を行いたい。

だけど、挙動としては、Controller に到達する前の Rack Layer で勝手に parse 処理が走ってしまい、 Rack Layer で raise されて勝手に落ちてしまう。

具体的には ActionDispatch::ParamsParserが先にパラメータを見ている。

吐かれるログはこんな感じ

Started PUT "/api/users/5001" for ::1 at 2016-07-07 16:24:16 +0900
Error occurred while parsing request parameters.
Contents:

{
  "user": {
    "email": "sample@example.com",
    "password": "cGFzc3dvcmQ=",
    "name": "田中太郎"
  }
}:
  /.rbenv/versions/2.3.1/lib/ruby/2.3.0/json/common.rb:156:in `parse'
  activesupport (4.2.4) lib/active_support/json/decoding.rb:26:in `decode'
  actionpack (4.2.4) lib/action_dispatch/middleware/params_parser.rb:44:in `parse_formatted_parameters'

ログに生情報がそのまま出てしまうし、リクエスト元にも同じ内容が返ってしまう。 さらに、リダイレクトやエラーメッセージの表示を制御できないのもマズい。

どうすればいいのか

middleware のスタックに、ActionDispatch::ParamsParser  よりも前にハンドリング用の middleware を差し込む。

今回自分は Committeeという Gem を使っていて、この Gem で定義されている ハンドリング処理に任せたかったので、

application.rb では以下のように指定した

config.middleware.insert_before ActionDispatch::ParamsParser, Committee::Middleware::RequestValidation, schema: JSON.parse(File.read(schema_file))

config.middleware.insert_before ActionDispatch::ParamsParser, Committee::Middleware::ResponseValidation, schema: JSON.parse(File.read(schema_file))

参考