VSCode に Integrated terminal という機能が追加されていた
VSCode 1.2.0 で Integrated terminal という機能が追加されていた。
大雑把にいうと、エディタのウィンドウの一部にターミナルを追加させる機能。
mix コマンドをコマンドパレットから実行できるように拡張機能を書こうとしてたんだけれど、Integrated terminal でいいじゃんって感じ。フォーカスを移動させるショートカットがまだわからないけど、拡張機能を書く意欲は下降気味。というか消失。
Visual Studio Code をコマンドラインから起動させる
問題
コマンドラインから Visual Studio Code を起動したいが、どう設定すればいいか不明。
環境
- Mac OS X 10.10.5
- Visual Studio Code 1.2.1
解決
コマンドパレットから shell Command: Install 'code' command in PATH
を実行する。アンインストールも同じ感じ。
参考
Ueberauth: (FunctionClauseError) no function clause matching in Keyword.merge/2
問題
phoenix に ueberauth_identity を組み込もうとしたところ、コンパイル時に (FunctionClauseError) no function clause matching in Keyword.merge/2
というエラーが発生する。
環境
- Elixir 1.2.6
- Phoenix 1.1.4
- ueberauth_identity 0.2.3
解決
config.exs に設定を追加する。
config :ueberauth, Ueberauth, providers: [ identity: {Ueberauth.Strategy.Identity, [ callback_methods: ["POST"] ]} ]
感想
エラーメッセージ・スタックトレースからでは原因の予想が全然つかなかった。 ドキュメントには、設定ファイルに追加しろって書いてある。。。
(PHPUnit 5 未満では)データプロバイダでモックオブジェクトを作成しないほうがいい
前提
PHPUnit 5 未満を使用している(問題の確認をしたのは PHPUnit 4.8.21)。
問題
指定したメソッドが一回だけコールされることを確かめるテストで、指定したメソッドが一回も呼ばれていないのにテストが成功してしまう。
モックオブジェクトはデータプロバイダで生成している。
具体的には
以下のコード(some.php)がある。このテストを実行すると失敗するはず。。。
なのだが、PHPUnit を実行すると成功してしまう。
$ ./phpunit-4.8.21.phar some.php PHPUnit 4.8.21 by Sebastian Bergmann and contributors. . Time: 141 ms, Memory: 12.00Mb OK (1 test, 0 assertions)
解決
- モックオブジェクトをデータプロバイダではなくテストメソッド内で生成するようにする。
or
- テストケース内で
$mock->__phpunit_verify()
を呼ぶ。
前者のほうがお行儀がよさそう。
参考
この修正でデータプロバイダで生成したモックオブジェクトでもテストが期待通り実行されるようになった(issue はデータプロバイダではなく、依存関係の上流のテストケースで生成したモックオブジェクトだけれども)。
PHPUnit 5.1.3 では期待通りの結果。
./phpunit-5.1.3.phar some.php PHPUnit 5.1.3 by Sebastian Bergmann and contributors. F 1 / 1 (100%) Time: 111 ms, Memory: 10.25Mb There was 1 failure: 1) SomeTest::testStubWithProvider with data set #0 (Mock_SomeClass_0cfc834a Object (...)) Expectation failed for method name is equal to <string:doSomething> when invoked 1 time(s). Method was expected to be called 1 times, actually called 0 times. FAILURES! Tests: 1, Assertions: 1, Failures: 1.
HTTPリクエストからChannelへメッセージを送る
GETやPOSTなどのHTTPリクエストを受け取り、その処理の中でChannelにデータを送信したい場合、以下のように書くことでメッセージを送信できる。
HelloPhoenix.Endpoint.broadcast_from! self(), "rooms:lobby", "new_msg", %{uid: uid, body: body}
http://hexdocs.pm/phoenix/Phoenix.Channel.html の "Broadcasting to an external topic" の箇所に書いてあったのを ここ に合わせて少し変更した。そこの例では channel 側のコードとして書かれているけど、controller 側のコードの中でも使えた(まあ、*.Endpoint モジュールの関数なので当たり前?)。
ちなみに、これで何をしたかったのかというと、fluentd でログを転送して、それをブラウザでリアルタイムで見れるようにしたかった。
こんな感じ。
+---------+ +---------+ Log -> | fluentd | | Browser | +---------+ +---------+ | A | | +-- HTTP(POST) +-- Websocket | | V | +-----------------------+ | Phoenix | +-----------------------+
コマンドラインの引数を得る方法
Elixirでコマンドラインのツールを書く方法が(自分の観測範囲内では)二通りある。
一つはスクリプトとして実行する方法。もう一つは、escript を使う方法(こっちの方法も名前からするとスクリプトとして実行されてるっぽいけど)。
スクリプトとして実行した場合、System.argv/0 を使えばいつでもコマンドに渡された引数を得ることができるけれど、escript を使った場合は System.argv は nil を返してくる。
ということのメモ。
スクリプトとして実行した場合
ソース
defmodule RunScript do def go(argv) do IO.inspect argv IO.inspect System.argv end end RunScript.go(System.argv)
実行
$ elixir run_script.exs one two three ["one", "two", "three"] ["one", "two", "three"]
escriptを使った場合
ソース
defmodule RunEscript do def main(argv) do IO.inspect argv IO.inspect System.argv end end
実行
$ ./run_escript one two three ["one", "two", "three"] nil
参考
escript を使った書き方は以下のページを参考にした。