トップ 追記

2018-07-13 [長年日記]

_ Laravelアプリはお手軽にscale outしないので注意が必要

Laravel で Form を利用して、エラーだった場合にそれをどう返すかのサンプルコードは 4.2 でも 5.6 でも以下のように

redirect で返すようになっている。

そして Form を組み立てる View 側では Input::old() を使うとよいということになっている。さっき入力していたデータを復元してあげないと不親切だからだ。

しかしこの組み合わせはクセモノ。

何が起きるかというと Session データに Form の Input すべてを載せることになるので、実質 Session Driver に Cookie は利用できない*1。つまり、アプリケーションサーバだけでカジュアルに scale out することはできないということになる。

Session Driver はすべてバックエンドのストレージ前提になり、DBMS や memcached, Redis などが必要になる*2。これらの準備が簡単なよくできた PaaS を使っているならよいが、そうでないならインフラの知識も必要になってしまうので、注意しておいた方がよさそうだ。

しかし、この Form の error を redirect で返す方法って Laravel のこのコードで初めて見たんだけど、こういう設計って推奨されるんですかねえ…?

Tags: PHP

*1 Input がどんな大きさになるのかはよほど注意深く作らないとコントロールできないだろう

*2 当たり前だが file は scale out しない。てゆーか DBMS に Session データを置くのも scale out しないような?


2018-07-12 [長年日記]

_ ChromeDriverを使ったE2Eテストは再現性に注意が必要

他の環境ではちょっとどうなっているのか分からないのでとりあえず Ruby 限定の話。

登場人物は以上。以下、メモ。

  • ChromeDriver は standalone server である
  • Ruby では ChromeDriver を利用しやすくしてくれる chromedriver-helper gem がある
  • これを使うと chromedriver を起動するコマンドとこれのアップデートを支援する chromedriver-update コマンドがインストールされる
  • chromedriver-helper gem のバージョンと chromedriver server のバージョンは一致しない
  • chromedriver-update を叩いた時点での最新バージョンが常に安定バージョンとは限らない
  • 明示的にバージョンダウンするには chromedriver-update <version> とする(helpは特にない)

これを CI で再現するには chromedriver-update をとりあえず叩くようにしておきつつ、コケたらバージョン指定してダウンするといった対応を即座にしていく必要がある。のかな? いや違うな、CI で動く Chrome のバージョンの変更を検知するところからか?

とにかく PhantomJS 時代と違って Headless Chrome でいこうと思ったら Chrome, ChromeDriver, chromedriver-helper gem のバージョンの情報を追う必要があるので、ちょっとこれまでより気を使うことが増えるなぁという感想でした。

Tags: Ruby Chrome

2018-07-10 [長年日記]

_ lodash v4以降のpairsがArrayとObjectの変換に便利

JavaScript は ES2015 以降、言語標準の機能が強化され、Array の操作だけなら別に Underscore / lodash は必要ないかなと思い、最近はできるだけ粘って入れないようにしています。

ですが、どうしても Object と Array の変換がコンパクトに書けません。

Ruby ならこういうので一発なわけですよ。

Hash[*[['a', 'b'], ['b', 'c'], ['c', 'd']].flatten]
# => {"a"=>"b", "b"=>"c", "c"=>"d"}

で、軽く変換方法を見るとまーだいたい副作用ベースで forEach で書くわけですけど、いやそれやりたくないなぁと思って、稀によく利用する lodash を調べたらありました。

_.fromPairs - Lodash Documentation

_.fromPairs([['a', 1], ['b', 2]]);
// => { 'a': 1, 'b': 2 }

なんてこった Ruby そのままというか、flatten がない分むしろスマートです。

逆もあります。

toPairs と toPairsIn の違いは本家ドキュメントを参照してください。

lodash v4 がリリースされたのが 2016年1月なのですが、コツコツ更新されてるんですねー。*1

さらに、「これだけのために lodash 入れるのやだなぁ」と思う方のために朗報。なんと、個別に npm があります。

こいつらを使えば必要な function だけを導入できるわけです。いやー至れり尽くせり。

Tags: JavaScript

*1 これを書いている時点で最新の 4.17.10 が 2018-04-24 リリース。Underscore.js の方も最新リリースが 2018-06 で継続中。


2018-07-04 [長年日記]

_ Vue componentのevent handlerのテストはwrapper#triggerから

単純なメモ。

<template>
  <container>
    <button @click="handler">押して</button>
  </container>
</template>

<script>
export default {
  methods: {
    handler() {
      // これをテストから直接呼ぶとrender済んでない可能性大
    }
  }
}
</script>

こんな Vue component があるとする。

端折りまくったテストコードはこんな感じに書けるんだけど、ここで handler() を直接呼んではいけない。

import Komponent from 'komponent.vue'
..

describe('Komponent', () => {
  var wrapper

  function mountComponent(component) {
    return mount(component, {localVue, router, ..})
  }

  describe('condition', () => {
    beforeEach(() => {
      wrapper = mountComponent(Komponent)
    })

    it('wrong example', () => {
      wrapper.vm.handler()
    })

    it('good example', () => {
      wrapper.find('button').trigger('click')
    })
  })
})

どうも直接 handler() を呼ぶと component が render される前に handler() が呼ばれてしまうらしく、少なくとも DOM 上のデータは取得できない。

単純なロジックだけのメソッドならこれでもテスト可能だが、event handler としてのテストをする場合はちゃんと event から呼んであげるのがよいらしい。

で、event を起こすには、まず event を起こしたい要素を特定してあげる。wrapper.find() で特定してあげると DOM wrapper のようなオブジェクトが取得できるので、そいつで event を trigger する*1。すると実際に Vue component が render されているような状態で handler() を動作させることができる。

※ ちなみに render という function も export されているのだが、これは @vue/test-utils ではなく @vue/server-test-utils に含まれるものであり、component のテストではなく、render された HTML に対するテストしかできない。mount や shallow の代わりには使えない。

*1 @vue/test-utils を使ったテストはとにかく wrapper を相手にする