ExUnitAssertMatchっていうパッケージを書いた
伝わる人には伝わる言い方をすると、https://github.com/r7kamura/rspec-json_matcherみたいなことがしたい。
例えばPhoenixのコントローラのテストとかで、レスポンスのJSONの形式をテストしたいときに
assert json["user"]["name"] == "John" assert json["user"]["age"] == 28 assert json["user"]["orgs"][0]["name"] |> is_binary()
とか全部書くのダルいし、もうちょいどんなJSONを求めてるのかわかるようにしたかった。あとElixirのパッケージ最近書いてなくて、リハビリしたかったというのもモチベーションの1つ。最初はマクロで実装しようと考えて書き始めたけど、そのまま機能追加してメンテしていく自信がなくなったのでやめて、以下のようになりました。
alias ExUnitAssertMatch, as: Match expected = Match.map(%{ "user" => Match.map(%{ "name" => Match.literal("John"), "age" => Match.literal(28), "orgs" => Match.list_of( Match.map(%{ "name" => Match.binary(), }) ), }), }) Match.assert expected, json
気をつけた点としては
use
させない- Configつかわない
です。マクロやめたのでuse
はまぁしないっしょというのはありつつ、他のパッケージのコードにuse
が入ってると結構コード読みづらくなるなーという実感があるので、自分がつくるものではやらんようにしよーというもの。Configややこしい問題はhttps://elixirforum.com/t/proposal-moving-towards-discoverable-config-files/14302とかhttps://elixiroutlaws.com/1でも言われていて、徐々に解決されていきそうだけど避けるようにしている。今回のパッケージはテストのときのためのものなので大して関係ないけど、設定っぽいものは引数で渡せるようにしてます。ex_unit_assert_match
って名前は長いなと思ったけど、https://hex.pm/docs/publish#naming-your-packageに従ってこうしてます。
趣味プロジェクトで使いながら、色々追加してこうと思います。
Gettextってよくできてるんだな、という感想
dev.toコードリーディング会に参加した
行ってきました。十数人で各々が好きなところから読み始めて、最後に見所や気づきを喋る流れでした。initializersを読んでいく人やモデル中心に見ていく人など様々。近日中に全員のメモが公開されるとのことですので、そのときはリンク追記します。会場を提供してくださったSmartHRさんありがとうございました。
先週金曜の dev\.to コードリーディング会に参加した皆さんのメモはこちらに公開されてますhttps://t.co/uipqG1pYxu
— ぷりんたい (@spacepro_be) 2018年8月13日
追記ここまで
以下は自分のメモ。やはりdev.toと言えば爆速なので、CSSをheadタグに埋め込んでいたり、キャッシュってどうやってんだろうなーといったところを中心に読みました。最後の所感にも書きましたが、爆速サイトをつくるためのイケてる最強プラクティスが詰まったコードを期待していた割に、泥臭さ100%のコードやら結構ひどいメソッドたちやらが溢れていて、歴史に勝てるものはおらんのじゃ...という気持ちになりました。users
テーブル辺りを見ると共感が得られると思います。やはり銀の弾丸は無く、歯を食いしばってひとつずつ問題をなぎ倒していくしか道は無いのです...。
なお、ハイライトは http://sushi.to というサイトが発見された瞬間でした。
headタグへのCSS埋め込み
render "layouts/styles"
- ページに必要なCSSをひたすら
.to_s.safe_html
- キャッシュ条件が結構ながい
- ここで
<% Rails.application.config.assets.compile = true %>
- 思っていたより泥臭いし、メンテできる気がしないけどどうなのか
- 大多数のページは
stylesheet_link_tag application
なので意外と大丈夫なのかも
- 大多数のページは
core_page?
で最小限のcssを読むか判定している- このcssはService Workerがはじめにキャッシュしている
- ページに必要なCSSをひたすら
Service Worker
- serviceworker-rails使ってる
- service-worker.js.erb
- serviceworker-companion.js
- 割と普通
- Homeにインストールの結果をGAに送っていた
どうやってCDNキャッシュしてるか
- bodyのdata属性にユーザ情報を埋め込んでいるが、これを非同期にやっているのでCDNにキャッシュできる
function initializePage(){ initializeLocalStorageRender(); initializeStylesheetAppend(); initializeFetchFollowedArticles(); callInitalizers(); } function callInitalizers(){ initializeLocalStorageRender(); initializeBodyData();
initializeBodyData
で/async_info/base_data
を叩いてbodyのdataに入れてる。入れたらlocalStorageにも入れてる。次回からはlocalStoreageから読み出してbodyのdataに入れてる。getUserData()
は15秒間待ってる。
function mouseoverListener(e) { if ($lastTouchTimestamp > (+new Date - 500)) { return // Otherwise, click doesn't fire } var a = getLinkTarget(e.target) if (!a || !isPreloadable(a)) { return } a.addEventListener('mouseout', mouseoutListener) if (!$delayBeforePreload) { preload(a.href) } else { $urlToPreload = a.href $preloadTimer = setTimeout(preload, $delayBeforePreload) } getImageForLink(a); }
マウスホバーでの先読みしてる。スマホはtouchstartListener
。
所感
CSS埋め込みとか、CDNエッジキャッシュするための工夫とか、もうちょっと高度な謎テクノロジーであのパフォーマンスを実現していると思っていたけど、読んでみたら想像を絶する泥臭さだった。総じて、この量のjsをテストほとんど無しで本当に書いたの...という気持ち。