[Elixir]Pin演算子のちょっとした確認

ElixirにはPin演算子があって、その挙動を少し頭に入れるために簡単なcase文をつくってみました。 Pin演算子は、変数の再代入を防ぐ、という役割を持ちます。 以下は引数として与えられた a が、 SamplePin.pin1(a) ではcase文では b=10 が再代入される SamplePin.pin2(a) ではcase文で b=10 が再代入されず、パターンマッチされる という例です。 Erlangの流れを持ちますが、再代入が許容されるElixirでの再代入という副作用を防ぐ手段ですね。More

[Elixir]belongs_toしているモデルのcontrollerのテストコードを修正する

belongs_toの関係を持つモデルを、 #show で描画するところのcontroller層の話です。そのとあるコードをテストする時、従属の関係にあるモデルをDBに生成しておく必要があるのですが、そのコードを書くにあたりEctoの知識が欠如しててつまづいていたけれど、うまくかけた、というメモ。 Userモデルは、Pageモデルの一部に従属(belongs_to)しているので、Userモデルの要素を取得する場合、PageモデルをDBに生成しておく必要がある、というコードです。 以下のshowがテスト対象となるもので、UserのRepoを取得してきて、それに対してSQLの IN (Repo.preload)をしてきて、その結果を描画するという内容。 それに対して、Repo.insertでPageを作成、その次に従属の関係を作るためにpage_idに生成したpageのidを代入したUserを用意する。 最後に、Repoを更新すると、最低限のデータが揃うので、showで表示する要素としては十分なデータが揃えられる、というものです。 Ectoの理解があるとひょいひょいっとできるのですが、そこが欠如していた時はどう書けば良いかよくわからなかったのですよね…More

[Elixir]Ectoを触ってみる

Elixirの軽量なORMであるEcto それの使いかたをざっと把握していくために少しEctoを触ってみました。 メモです。 対象 標準的なクエリ とか これらはいずれも、以下のようなクエリが発行される。 パイプで接続されたEcto.Queryはクエリを結合していくのですね。 他、以下のようにlimitをかけることも可能。 preloadを行う belongs_to などで関係を持った、異なるテーブルに対してクエリを投げる場合、以下のようにpreloadを使います。 Ecto.Repo#preload/2 は、以下の通り IN で統合したテーブルに対してクエリを投げるのですね。この時に発行されるクエリは以下。 なるほど。More

[Elixir]Plug.Testを使ったRequestのテスト

作業メモ。 Elixir 1.0.5 Phoenix 0.14.0 Plug.Testを使ったやつ テスト対象 テストコード Phoenixを使ったやつ http://www.phoenixframework.org/docs/introduction test_helper.exs で、test用DBのcreate、migrationを行っているのですね。 test/test_helper.exs ファイル単位とか、以下のように行単位でテストできるのですね。 タグの付与と実行 moduleへのタグ moduleへのタグ定義 実行 実行 特定のタグのみ除いたテストケースの実行 test case個別へのタグ タグの定義 実行 特定のmoduleを除いたうえで、individual_test:yupを実行する ランダムにテストを実施する これ、面白いなーと感じました。 🙂 テストの自動生成 以下のようにcontroller、modelを作成したら、テストケースも自動生成されていました。 作成したモデルに対する、基本的なテストケースの自動生成良いですね。 ざっと生成されたテストケース見てみると、moduleで作成したリソースの生成/更新などの基本的な正常系、作成失敗などのエラー系。 ちなみに、以下を実行した後だと、 phoenix.gen.html とうViewも自動生成されるので、かなりお手軽。 test/controllers/user_controller_test.exs test/models/user_test.exs HelloPhoenix.ModelCase は、 test/support/model_case.ex で実装されている。More

[Elixir]Plugのコードを少し読んでみる

PhoenixのPlugの説明を読んでいると、Plug自体の動きが少し気になったので読んでみました。 ここでは、以下の Hello World を追ってみることに。 https://github.com/elixir-lang/plug API Document: http://hexdocs.pm/plug/ Plug自体、簡単なWebサーバの機構を提供するものですね。 ひとまず、 を実行してみる。 まずは以下が呼ばれる。 https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L41 この中を辿ると、 run(:http, plug, opts, cowboy_options) にいきつく。 ここで何しているかを見てみる。 https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L118 なるほど。最終的に、Cowboyを実行しているのですね。これはErlang向けの軽量なWebサーバらしい。 Cowboy https://github.com/ninenines/cowboy 返り値として、 {:ok, pid} のタプルを返す。 試しに、もう一度実行すると以下のようにerrorを得られる 今度は :error のタプルですね。:already_started が得られているので、pidを得たい場合、 とすれば得られます。なるほど。 ちなみに、停止するときは、 とします。 これは、 https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L96 を参考にすれば良いですね。ここで与える :ref は、起動時に与えた Plug.Adapters.Cowboy.http MyPlug, [] の中の MyPlug という名前。 これは、以下のコードを見てみると、確かに:refの引数( build_ref(plug, scheme) )としてplugを与えているのでわかります。 https://github.com/elixir-lang/plug/blob/master/lib/plug/adapters/cowboy.ex#L35 なるほど。Plugというか、Cawboyの理解が少し進んだぞ。 %Plug.Conn{}…More

[Elixir]パターンマッチを使って条件分岐を関数で分ける

Elixirは関数定義の引数に対してパターンマッチを利用できます。 ちょっと、ちゃんとElixirっぽくしようということで使ってみました。 対象は以下。 https://github.com/KazuCocoa/simple_app_reporter_ex/blob/master/lib/reporter.ex get_body_json という関数は、HTTPoisonのレスポンスを引数として、そのレスポンスに適した処理を行うというものです。 修正前 caseを使って、得られたHTTPoisonのレスポンス毎に処理を分けています。 1つの関数内で条件が分岐するので、関数内の処理が必然的に多くなります。 修正後 関数定義の引数でパターンマッチを利用しています。上記の case における条件がそのまま関数定義になります。 この結果、 get_body_json() という関数に値を与えると、引数のHTTPoisonの状態によってElixirが勝手に処理を分けます。 1つの関数が過度に肥大化しなくなり、関数が最低限の責務を持つようにプログラムできるのが良いですね 🙂 締め Elixirは、条件分岐を処理する方法として 関数定義 case if cond がありますが、個人的には上記の順で考える頭を作っていきたいなと思ってます。 テストシナリオを書くときも結構条件分岐は出てくるのですが、こういう感じで責務を分けることができると処理を集中できて良いなーとふと。More

アプリのレビューを新着順で取得するライブラリをElixirで実装してみた

過去、 GooglePlay/AppStoreのレビューを取得するスクリプトを少し整えた のようにRubyでAppStoreやGooglePlayで新着レビューを取得する実装を書きました。 それを題材にElixirを使って同様のライブラリを書いてみました。Elixir歴は、Getting Startedを1巡したくらい。 GitHub https://github.com/KazuCocoa/simple_app_reporter_ex Hex https://hex.pm/packages/reporter Doc http://hexdocs.pm/reporter/0.1.1/ HTTPoison、Poison、Quinn、Flokiを使って、HTTP通信やJSON、XML、HTMLスクレイピングを満遍なく触った気がします。 テストデータ用意してのDocTestや、ExUnitなどもザーッと触りましたが、Elixirというか、Erlangの良さであるprocessを使った並行実行は実装していません。 もう少し気が向けば触っていこうかなと思っている次第。More

Learning META-PROGRAMMING IN ELIXIR

Macroに関して学んだ。 quote で与えた文字列を Abstract Syntax Tree (AST) としてタプルで得ることができる。 unquote は、quoteで囲まれた中で使うことでquoteの中でunquoteした要素をinjectすることができる。 quoteやunquoteなどはこちらで確認可能。 他にもこちらとか。 defmoduleの中で @before_compile TestCase のように記述することで、コンパイル時にTestCase.__before_compile__/1を実施することができます。このようなModuleに対する定義は以下を参照すると良いとか。 http://elixir-lang.org/docs/stable/elixir/#!Module.html Getting Startedをすべて終えた… Macroなんかはまだ馴染まないとなーという感じですが、単純なコードは読み書きできてきた感じ。 ちょっとやりたいことがあるので、Phoenixのtutorialを読んでいこうかな。More

GimeiのElixir版を練習がてら書いてたらちゃんとしたものが公開された

まだElixirのチュートリアルをちゃんとやり始めて1週間くらいなのですが、ここ最近、Elixirを学んでみています。チュートリアルも終わり何か書きたいな、と思った時、Gimeiが他言語でポートされているブーム?みたくなっているぽいことを知りました。 ひとまず練習がてら同じようなものを実装しながら学ぼうと思い、以下のような練習リポジトリを作り、少しづつ手を動かし始めました。Hexで公開してからリポジトリを公開しようかなと思ってたのですが、作っている途中にちゃんと経験されている方が書いたgimeiのElixir版が出ていたのを昨日見つけたので、まだ全然途中で中途半端な感じなのですがprivateからpublicにしていいかなーというくらいのノリでリポジトリをpublicにしました。 もしElixirに興味のある方は、後者のgimei_exを使いましょう。 私のやつ https://github.com/KazuCocoa/elixir-gimei ちゃんとしている方 https://github.com/ma2gedev/gimei_ex 私のリポジトリは機能的にもまだ未完全です。また、DocTestを使ってみたりと違ったこともしています。これからも多分色々TODO増減しながら試していきそうです。Hexにあげるまではしてみたいな。 Erlangのライブラリ探して使ったり、関数型のような記述をしたり。まだ手続き型の考えのほうが強いですが、caseやrecursiveな書き方は、Elixirは好きな感じです。Elixir学んでいるとErlangも学ぶこともできるという特典付き。 ともあれ、こういう新しいものを学んで世界を広げるって、良いですね。More

MIX AND OTP vol 2

Mix and OTPの後半。 ETS ここは、GenServer、Supervisor付近の説明から。 リンク http://elixir-lang.org/docs/stable/elixir/#!GenServer.html http://elixir-lang.org/docs/stable/elixir/#!Supervisor.html ソースコードは以下 https://github.com/elixir-lang/elixir/blob/v1.0.4/lib/elixir/lib/supervisor.ex processによる状態の保持と、etsによる保持はいくつか違うところがあります。 processに状態を保持する場合、そのprocessが死んだらそれに保存されるデータも無くなります。一方、etsは複数のprocessに共有されるキャッシュのように扱うことができます。 共有キャッシュのように扱うことができるので、etsに対しては書き込み制限をしたりします。また、callbackに関しても同期的に行う必要がるなどの制約がでてきます。 ここら辺の説明がされますが、etsを生成したprocessが死んだ場合、etsも合わせて自動的に閉じられます。これは、etsはそれを起動したprocessにリンクされているから。 ということは、supervisorで起動させて、publicにするとprocessに依存して、それが死ぬとetsが閉じられるという事態も回避できそうです。 このページの最後の箇所の、 :ets.foldl() のfnへの引数で、 {name, pid} が与えられているのですがこれがどこから来たのかよくわからなかった… のですが、 の所を見て納得。 :ets(table) に保存していた値がfnの引数として与えられ、それに対して関数が適用されて出力が得られるというものなのですね。説明にもさらりと描かれているのですが、initの中に突然nameとpidが出てきたので???になりました。 このfoldlのErlangによるspecは以下。 pipelineでメソッドチェインぽく描くとき、 () はsつけるべきなのですね。そのほうが意図が伝わるコードになりますし。引数の数が違う同名の関数もあるので、これはすごく納得。 なるほどなるほど。 Task and gen-tcp Taskは、非同期に処理を行うprocess。 processなので、そのprocessを監視するためにsupervisorへの登録が大事になってくるのですが、そこの詳しくはTask.Supervisorをみると良さそう。 こうざっと読んでみると、Supervisorが非常に重要な位置をしめて、そのsupervisorが監視する子プロセスへの再起動strategyも大事。これらがErlangというかElixirの安定性を支えているのですね。 結構、Unit testでロジックをしっかりかかないと、ここはdebugとかスキル必要そうだ。。。 Docs, tests and pipelines ExUnit.DocTest、半端ない。ドキュメントがそのままiexのコマンドベースでのテストコードに置き換わるのですね。 http://elixir-lang.org/docs/stable/ex_unit/#!ExUnit.DocTest.html 例えば、以下の@docで囲んだドキュメントになる範囲の iex> とその次の行がコマンドと期待結果になって、テストが実施される。APIとして目に見えるインタフェースでは、このテストかなり役立つのでは。autodocみたいなものですね。 ここは、最後はどのようなテストコードを作っていくか、というのも含め、戦略はチームで形作っていく必要あるよね、ってもので終わってました。 Distributed tasks and configuration 最後は、異なるノード間での通信が話題です。ネットワーク越しに異なるノード間で通信をやりとりし、一方から送った処理をもう一方のノードで実行するということが可能です。 Node.spawn_link/2 を使うのですが、普通に使うとsupervisorの管理下に置くことができないので、以下の3通りが紹介されています。…More