I implemented simple posting app reviews to slack with Elixir-Slack(version 0.2.0) and Reporter(version 0.2.5). Base implementation to handle post to slack with Elixir-Slack This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.…More
Category Archives: development
『Programming Phoenix』を読んでみた(まだドラフト版)
ElixirによるRoR実装と表現される、Phoenix Frameworkの作者による書籍『Programming Phoenix』を読んでみました。今はドラフト版ですが、こういうフレームワークの基本的な思想とか好きなのと、PhoenixはElixirのmacroを駆使しているという話をみて、気になって買って読んでみました。(Elixir、macroがほぼそのままLips形式の記述なのですが、そこも著者は気に入っているそう。) 以下ではElixir 1.1.0、Phoenix 1.0.3を対象としてます。 内容としては、簡単なサンプルを作りながらPhoenixの話、Ecto、Plug.Conn、Ecto.QueryなどのElixirの基礎要素の話がありました。テストの話なんかはまだ書きかけ。Phoenixの話ばかりと思ってたら、結構Elixirの周辺の機構の主要な要素をかいつまんでいて、良い意味でびっくりでした。 個人的には、 https://github.com/KazuCocoa/web_qa_vote で作っていたことがこの書籍読んだあとだったらもっとサクッとできたのかな、という感じでした。ある程度Elixirの文法わかって、簡単なWebアプリ作ったことがある人が、中身を理解するという段階で有用な書籍っぽい。 技術的なところは置いておいて、個人的に面白かったのは、所々でてくる、著者らによるコラムです。なんでこうしたか?というところに、どのような意図があってこうした、というのが散らばってます。 例えば、Phoenixの内部処理ではAtom keyを使うけれど、外部(開発者)はString keyでパラメータを書く。これは、データの安全性への考慮を含めているから、というような。Phonenixの web ディレクトリと lib ディレクトリの役割の違いなど。あと、HTMLのtemplateの処理がPhoenixではなぜ早いか?というところに対しては、Phonenixは、templateをStringではなくlinked listsとして扱っているから、そのぶん性能的な改善が見られる、らしい。 以下、書籍のまとめとかではないけれど、個人的に派生して読んだり学んだことのメモ。 Phoenixのテンプレート的な話 Viewを生成するとき、以下の Phoneix.HTML.safe_to_string の関数を通して、 :safe 要素を持つTupleでViewのhtmlを表現したりしている。 https://github.com/phoenixframework/phoenix_html/blob/master/lib/phoenix_html.ex#L156 Dive to logic of authorization 認証機構の実装の話も扱っていたので、ついでにGuardianの中身も覗いてみました。結構似たことしているので、初見では読み悩んでいた箇所もスラスラ読めるようになっててびっくり。 例えば、sign_inした状態のsessionを作り出すときの話。Guardianを使う場合、以下のような処理を書いたりします。 この中で、 Guardian.Plug.sign_in/4 を覗いてみると以下のような処理をしています。 guardian/lib/guardian/plug.ex この中でパイプでつながっている set_* 系のものを見ていると、 Plug.Conn.* のPlugの機構の中で put_session とかしてて、いろいろ conn に Map.put して情報を付与していることがわかります。 つまるとこ、Guardianは conn の構造体にあるassignsやstateなんかのキーに値を追加していっているのですね。なるほど。ちなみに、 put_session は、 Plug.ConnのprivateのMapに独自の情報を追加していくのですね。…More
[Elixir]power_assert_exをex_parameterizedと組み合わせて使ってみた
Power AssertのElixir版を、 @ma2ge さんが作成されていたので、ex_parameterizedと合わせてみました。ex_parameterizedは、パラメータ化テストの記述を支援する、簡単なマクロです。 power_assert_ex https://github.com/ma2gedev/power_assert_ex ex_parametarized https://github.com/KazuCocoa/ex_parameterized やることは簡単。単に、 use ExUnit.Case を use PowerAssert に置き換えるだけでした。 ex_parameterized自体、単に test マクロを内部では使っているだけなので、特に変なAST操作は行っていません。なので、問題なく表示されました。すごい。 以下は、ex_parameterizedのテストをわざと失敗させた時の出力結果です。 まだ色々と制限もありますし、ExUnitの結果自体そんなに読みにくいテスト結果なわけではありません。ただ、なんだかんだでテスト結果を観察することが楽になりますので、良いなーと思いました。More
[Elixir]Plugを使ってたときにPhoenixの1request-1processが気になったので追ってみた
ちょっとしたHTTPの処理を受けるサーバを Plug を使って実装してようとしたら、 Plug.Adapters.Cowboy.child_spec() をすることになりました。また、trotも少し処理を追ってみると同様なところに行き着く。 ふと作業している途中で、Phoenixだと、1 request – 1 processとなるendpointの処理は結局はどこが処理してそうなっているのだろう、という疑問がわいたので、 すべきことを横に置いて さかのぼってみました。 過去、似たようなところとして以下のようなものを追っていました。 [Elixir]Phoenix.Router付近やendpointを追ってみる [Elixir]PhoenixのSupervisorのstrategy 開始地点 ひとまず、雑に Plug.Adapters.Cowboy で検索してみました。これは、Elixirの機構を使っているなら、最終的に同様にPlugにいくだろう、とのことから。 すると、Plug.Adapters.Cowboy.Handler なんかが検索に引っかかります。 この中から、 Phoenix.Endpoint.CowboyHandler の child_spec の中で使われているのを見つけました。この child_spec は、Subversion Treeの中で呼ばれます。 同様に、このHandlerをみてみると、この行にて、 が呼ばれていることがわかります。つまり、Phoenixのendpointの処理は、最終的にはPlugを使い、Cowboyへと向かっているのですね。 なるほど。 Subversion Treeを遡る もう少し、今度はSubversionがどのように流れているのかを追ってみました。つまり、 Phoenix.Endpoint.CowboyHandler がSubversion Treeの中で呼ばれるところを探す、です。 検索してみると、Phoenix.Endpoint.Serverで、 として定義され、この@handler が同じファイル内の initの箇所で呼ばれています。 じゃあ、このPhoenix.Endpoint.ServerをどのSubervionが呼んでいるのか?というと、Phoenix.Endpoint.Adapterで呼ばれていました。 もう少しさかのぼると、 Phoenix.Endpoint.Adapter は Phoenix.Endpoint の def server()内で stat_linkされるようです。この server() は、同じファイルの __using__ で呼ばれているので、Phoenix.Endpoint…More
[Elixir]defmacroに2つの要素を持つTupleを与えるとき、例外的にTupleがそのままASTとして使われる
ex_parameterizedを修正していたときに遭遇した振る舞い。 以下の通り、簡単な defmacro でマクロを定義していたら、 Example.a(do: {1, 2}) のように、この場合だけ意図しない出力が得られました。 これ、 Example.a(do: {1, 2}) の出力として [do: {:{}, [line: 11], [1, 2]}] が得られないといけない、と思って 聞いてみた ら、これは以下の通り問題ないみたいですね。 http://elixir-lang.org/docs/master/elixir/Kernel.SpecialForms.html#quote/2 Quote literals Besides the tuple described above, Elixir has a few literals that when quoted return themselves. They are: つまるところ、この defmacro の中身の Example.a(do: {1, 2}) は、 {key, value} のtupleに該当するから [do: {1, 2}]…More
Stetho1.2.0でScreenchastingが実現されている
Stetho1.2.0がリリースされていたので、私向けのメモ含めて。 Changelogはこちら New Chromeへのscreencasting initalizeするのが楽になった 他にも、SQLに対してEXPLAINできるようになったり。ElementタブからCTRL+Fして要素を検索できるようになったり。 initalizeが楽になった 今まで、複数行を使って Stetho.initialize に与えていたものが、1行に済むように。例えば以下。 Screencasting ChromeDevToolsの機能を使って、AndroidのViewをChrome上に表示させる、という機能です。(ChromeDevTools自体、こういう機能あったのですね。この機能を知るまで、全く知らなかったです…)それがStethoに統合されました。 統合するPR ただ、以下だとキーボードが表示されているのですが、Viewを取得するだけなのでシステム側のViewを持ってくることができません。なら、システムダイアログなんかは取ってこれなさそう。 少しコード見てみると、確かに activity からViewを取ってきているので、そうっぽい。 https://github.com/facebook/stetho/pull/190/files#diff-ac2bcff06c8c53f332d091e75117b95cR87 たとえば、ここの機能だけをみると単純にAndroidアプリをブラウザ上から操作する場合は以下のようなサービスが存在します。 http://www.vysor.io/ http://openstf.io/ これらと比べて技術的にChromeDevToolsを使ってStethoはどうようなことを実現されているぶん、実現も容易になっていそうです。このコードの変更箇所を少し覗いてみましたが、思いの外少ない実装で実現されているのですね…STFはもっとチューニングしてそうなので、ちょっと毛並みが違いそうですが。 https://github.com/facebook/stetho/pull/190 締め Screencast自体、いろいろ楽に類似サービスみたいなやつ構築できるようになりそうですね。サービスではなく、内々で使うには十分な感じものもが。時代はChromeDevToolsかなー。More
[Elixir]Parameterized Test with macros
hex.pmになかったのと、macroの練習がてら parameterized test の記述をサポートするmacroを書いてみました。 すごく簡単なminimamなmacroです 🙂 https://hex.pm/packages/ex_parameterized https://github.com/KazuCocoa/ex_parameterized こんな感じで test_with_params を接頭辞として使います。 内部では、 test をそのまま使っているのと、 line numberをそれぞれのテストケースで使っているので、テスト失敗した時でも何行目のパラメータで失敗したのかわかるようになってます。 Javaだと、@RunWith(Parameterized.class) や @RunWith(Theories.class) を使って書くやり方が推奨されているやつですね。(過去のBlog) RubyだとRSpecのモジュールやminitestとかでも実装されていますね。More
[Elixir]Elixirのライブラリ眺めてたらErlangのhttpcにたどり着いた
今はやりのElectronに触発されて、というわけでもないですが、ElixirでTwitterのStreamを取得できたりするライブラリである、ExTwitterの処理の一部を追ってみました。 その中で、 https://github.com/parroty/extwitter/blob/8820af239217a0f17864fd444fc71e451d5f5d79/lib/extwitter/api/streaming.ex#L92 ここの、以下のような process_stream の関数に含まれる receive のパターンマッチがイマイチ理解できませんでした。というのも、このライブラリの中に send self, {:http, …} というような応答を生成するところがなく、どこからこの receive にメッセージが来ているのだろう、とよくわからなかったからです。 結果的に、Erlangの httpc モジュールから来ているのだとわかったのですが、その中で最終的にErlangモジュールまで手を出すようになったので、私の後学の意味も含めてメモを残しておきます。 process_stream の場所 まずは入り口からです。Streamを取得する stream_filter の処理を追うと、以下メソッドに行き着きます。 https://github.com/parroty/extwitter/blob/8820af239217a0f17864fd444fc71e451d5f5d79/lib/extwitter/api/streaming.ex#L19 この分岐を持つ関数 process_stream は以下箇所で初めて呼ばれます。 https://github.com/parroty/extwitter/blob/8820af239217a0f17864fd444fc71e451d5f5d79/lib/extwitter/api/streaming.ex#L48 spawnとして別プロセスにメッセージを送っている箇所を知る ここをみると、spawn としてプロセスにメッセージを送っている処理の中で、 ExTwitter.OAuth.request_async をよんでます。 これを少し追うと、以下に行き着きます。 https://github.com/parroty/extwitter/blob/8820af239217a0f17864fd444fc71e451d5f5d79/lib/extwitter/oauth.ex#L23 erlang-oauth に足を踏み入れる このモジュール :oauth はErlangの erlang-oauth というモジュールだそうです。そこで、少しそのモジュールの get を追ってみます。引数6個なので、以下だとわかります。 https://github.com/tim/erlang-oauth/blob/master/src/oauth.erl#L24 ここでhttp_requestをみると、 httpc:request/4 を呼んでいることがわかります。 https://github.com/tim/erlang-oauth/blob/master/src/oauth.erl#L193 Erlangのhttpcドキュメントを追う ここで、Erlangのドキュメントをみてみました。 http://erlang.org/doc/man/httpc.html#request-4 また、 Options に関してはその内容が以下のように書かれていました。…More
[Elixir]SupervisorとWorkerの再起動の振る舞いをちょろっと見てみた
ちょろっとしたお遊び程度ですが、Supervisorによって管理されているプロセスをkillしたりしてプロセスをみてみました。書籍には載っているのですが、特に何も見ずにお遊び程度にサラでやってみたのでそのメモ、みたいな感じです。 初めに… 空のsupervisorプロジェクトを作ります。 $vim lib/supervisor_test/neko_supervisor.ex $ vim lib/supervisor_test.ex Supervisorの確認 Supervisor.count_children/1 を使い、親のSupervisorのしたに :neko の子workerがぶら下がっていることを確認してみます。 workerをexitしてみる Supervisorの one_for_one では、監視対象のプロセスが終了したら、異なるPIDを持つプロセスを起動する、というstrategyでした。Supervisorをexitしてみて、その挙動を実際に確認してみます。 Supervisorにぶら下がる子workerをみる ここで、親のSupervisorのPIDを元に、そのしたにぶら下がっているプロセスをみてみます。 1回exitした one_for_one の子プロセスである :neko 、exitしたら再度立ち上げられていますね。ちゃんと、PIDが異なる値になって、別プロセスが立ち上がっていることも確認できました。なるほど。 子プロセスを終了させる、という意味だと、Supervisor.terminate_child/2 もあるのですが、こちらはSupervisorから終了させるので、停止させたら復活しませんでした。その後、Supervisor.restart_child/2 で再び動き始めます。なるほど。 One More Thing Supervisorをkillしてみます。すると、Supervisorの子も全て終了していることがわかります。まぁ、そうですよね。 このようにSupervisorが落ちるとその子も落ちるので、Supervisorを階層でつなげて、それぞれに対しても様々なstrategyを設定できるようにすることが大事ですね。そこらへんの設計が大事で難しい、という話もElixir in Actionで触れられてたなー。 分散環境はやっぱり大局的な設計はすごく大事。More
[Elixir]Phoenix.Router付近やendpointを追ってみる
Phoenixのrouterにおける、macroによる動的な関数定義を追ってみました。その備忘録。 macroを多分に使っているといわれるPhoenixの入り口を覗いて仕組みを少し知ることが目的です。きっと、ここら辺追えるとテストフレームワークとかそこらへんも追ったり作れるだろうと踏んで。 まず、入り口のおさらいから。 macroによる定義のおさらい Sample Caller の2種類のモジュールを定義します。そのうち、 Sample では様々な方法で関数を定義します。Caller では、その Sample を use して、定義されたマクロの1つである my_def を使い関数を定義、実施します。こうなると、例えば my_def が get などで置き換わった時、その引数となった文字列を関数のように扱いそのブロックを実行する、ということも可能になります。 (最後には実際のPhoneixを使い、追ってみます。) SampleとCallerのモジュール定義 サンプルコードを以下に貼り。注釈でそれぞれのメモを追加してます。 これを sample.exs と保存して、以下のCLIを実行します。 Sampleの実行それぞれ 補完される内容 neko() は、quoteで囲まれたところはASTとして得られます。 inu() は、quoteのなかで、unquoteしてneko()を呼んでいます。 pig_a などは、 def unquote(String.to_atom(@value “_” num))() do と :atom として定義、unquoteされた要素は動的に関数として定義されます。 Callerの実行 補完される内容 my_def で定義した my_neko は、 @my_sample に要素として登録され、compile timeで MODULE の関数として登録されたものです。 __using__ で定義されたrunを実行…More