ラーメンが食べたく

技術的なメモや、僕の気持ちです。

Spacemacsを捨てAtomを再び使うことにした

こんにちは、最近テキストエディタAtomに移行したすずきです。 今この世の中にはテキストエディタがたくさんあります。僕はいま高校二年生でプログラミングを初めて3年くらいしかたっていないのですが、以下のようなテキストエディタ変遷を行ってきました。

まず、僕は最初Unityでゲームを作って遊んでいたのでMonoDevelopでした。途中、変なおじさんにSublimeTextをオススメされたのでMonoDevelopをやめSublimeTextを使い始めました。その後変なおじさんは僕の前から姿を消し、僕はJavaで遊ぶためにそれに適した開発環境を探し、Eclipseにたどり着きました。その後すぐ高校受験という奴がやってきて、僕は一時期プログラミングを辞めていました。でも辞めきれなかった僕はwebプログラミングがしたいということで、htmlやらcssやらレガシーがjavascriptを書き始めました。その時にSublimeTextに戻りました。そしたら変なおじさんがAtomをすすめてきたのでAtomを使い始めました。言われるがままパッケージを入れまくった僕のAtomは瞬く間に軽快な動作を忘れていきました。もうこんな思いテキストエディタは嫌だ!と嘆いていた僕の目の前にvimが現れました。いま考えれば、Atomの不要なパッケージを消してvim-modeを入れればよかったわけですが、当時の僕はその軽さと独特ながら確かな操作性を持つキーバインドに惚れたしばらくvimを使っていました。その後頭のおかしな友人がSpacemacsというテキストエディタを使っているのを見かけたので、おもしろそうだったのでなんとなくインストールして遊んでいました。秒で惚れてしまいました。SpacemacsはEmacsの上で動きますが、vimキーバインドをそのまま使うこともできます。完全に一生お前と生きていくと決めた僕でしたが、使っているうちにじわじわと問題点が浮かび上がってきました。

Spacemacs困りポイント

  • CLIで動かすと結構な頻度で落ちる
    • vimemacsの長所として、CLIで動くというのがあるんですが、CLIでSpacemacsを動かすと結構な頻度で落ちます。落ちる度にSpacemacsが落ちているのではなく、私が上昇しているのだ。と言い聞かせてきましたが、我慢の限界がきてGUIEmacsに乗り換えました。この時点でそれがEmacsである利点が1つなくなりました。
  • 開発の停滞
    • これが一番大きい。Spacemacs自体の開発がほぼ止まっていました。この記事は2017/12/16に書いていますが、直近のコミットは2017/11/2でその前のコミットが2017/9/7、そしてその前が2017/4/7でした。有志のOSSなら仕方のないことで、責めたりとかそういう話では全くないんですが、開発の停滞したテキストエディタを使い続けるのは非常にリスキーな気がしてなりませんでした。
  • Flow
    • 僕は普段Javascriptでreactを書いてるんですが、静的型が欲しくなります。FacebookOSSにFlowというのがあって、それを使うことでJavascriptに静的型を導入することが可能になるわけですが、flow-for-emacsの開発も停滞(というかちゃんと開発する気ない?)していて、しんどさを感じていました。Spacemacsにはlayerという概念があってそれを用いて機能の拡張を行うことができるのですが、flow-layerたるものは当然存在せず上記の「Spacemacsの開発の停滞」というのが響いているのかなぁという感じです。

以上の点を踏まえて移行コストとSpacemacsを使い続けるコストを天秤にかけて考えたら、移行が妥当だろうという結論に至りSpacemacsを捨てることに致しました。約一年間、ありがとう。

なんでAtom

Atomを選んだ理由はいくつかあります。

  • なぜvimではなくAtomか。
    • 別にvimでもよかったんですが、GUIEmacsを使うのに慣れ始めていたのでCLIエディタにこだわる必要が特になかったからです。それに自分は熱心なvim教徒というわけではなくVimScriptでバリバリ拡張を書くタイプの人間ではなかったので、vimを使う選択肢はありませんでした。(キーバインドvimです)
  • なぜIDEではなくAtomか。
    • 使い方を覚えるのが面倒だったから、という逃げの理由です。以前Eclipseを使った時や一時期AndroidScalaをした上での感想なのですが、IDEの使い方を覚えるコストが高すぎると感じました。Scalaのように様々なことが静的に確定する言語ではIDEのちからは存分に発揮され、生産性を生みそうですが、普段動的型付Javascriptばかり書いている僕には使い方のしれてるAtomの方が易しいと思いました。
  • なぜSublimeTextではなくAtomか。
    • オープンソースだから。というのが主な理由です。困ったらソースを見ろ、ができるので。ちなみに仮にSubmimeTextがOSSでもAtomを選んでいたと思います。その理由としては僕がpythonを読み書きできないからです。
  • なぜVSCodeではなくAtomか。
    • VSCodeでもよかったんですが、昔使っていて使い勝手が多少わかっているから、という理由でAtomにしました。今後Atomに大しての不満が募ってきた時に乗り換えるナンバーワン候補です。

で、どうなの

Atom、普通にいいと思います。ショートカットとかで迷う面もありますが、それは慣れの問題であってエディタの問題ではないので、Atom自体は優秀なテキストエディタだと思います。SpacemacsはEmacsなのでelispでカスタマイズできますが、僕はelispが全然書けないので、そこがあまり利点にはなりませんでした。Atomはjsでプラグインが書けるので、個人的に拡張がしやすいというのもあります。ここまで読んだらわかると思いますが、エディタの選定には個人の得意な言語や生い立ちに大きく左右されます。自由に選ぶと幸せになれると思います。

他校生からみた新座総合(主に情報科一部)

こんにちは、@tako_programingです。外部生なのに、NSGアドベントカレンダーの1枠を頂けたということで、他校の生徒の目には新座総合技術高等学校はどのように映るのかについて書こうと思います。

前提

  • 僕は千葉県にある偏差値60前後の普通科の県立高校に通う男子高校生です。
  • 2017年12月現在で、高校二年生です。留年等はしていません。
  • 主に僕との関わりがあるのは、現在の情報技術科3年の一部と、彼らに関係する生徒です。

きっかけ

 まず、僕が新総と関わりを持つようになったきっかけについてお話します。僕はtento.techというコミュニティで新座総合の情報技術科の一部の変な人達と出会いました。第一印象としてはとにかくおもしろかったです。彼らは技術者でありながら男子高校生です。そのため、プログラミングの話をした五分後にオ◯ホールの話をしている、なんてことが頻発します。今でこそ自分もそんな感じのノリについていけていますが、当時の僕からしたら不思議な雰囲気でした。あと、加納とか石坂は身長が高いので若干怖かったです。今でも色々おっかないですが。最近知りましたが石坂は転学しましたね。わけわからん。

技術力

 僕は、情報科の一部の人としか関わりませんが、彼らに限って言えば、年齢の割に馬鹿みたいに高い技術力と技術に対する興味があると思っています。1月にn十万稼いでくる高校生がそうそういてたまるかって話です。

 ですが、一部を除く情報科の話を聞く限りでは、この人達は今まで情報のなにを学んできたのだろうか、と思うほどに技術力が低いように感じます。周りに実際に情報技術を使って稼いでいるクラスメイトがいるのに、なぜ教えを請おうとしないのか、純粋に疑問に感じています。普通に羨ましいです。情報科に編入したいとは微塵も思いませんが 。

文化祭

 私は今年と去年、文化祭を見るために千葉県から新座総合まで足を運びました。遠い。去年の文化祭では、文化祭の公開時間前に、なぎ◯るとかのし◯んの手を借り、@tock203と共に校舎内に侵入しトイレに潜伏するものの、教員に見つかり、追放される等していました。その後、な◯まるとか◯しゅんは捕まっていました。とても申し訳ないと思っていますが、今では彼らにとってはいい思い出となっていることでしょう。

 新座総合の文化祭と言えば、きっと魔剤カフェを思い浮かべる方が多いのではないでしょうか。私もその一人です。一番印象に残ったのは二年連続で現在の三年情報科による魔剤カフェでした。カフェってなんなんでしょうね。もうよくわからなくなってきました。ですが、なんか楽しめる所では(意欲のある者で)一丸となって徹底的に楽しもうとするその姿勢は、普段の学校行事を冷めた態度で参加していた自分の目には少しうらやましく映りました。

Twitter

 統計をとったわけではないので、正確なことはいえませんが、新座総合はTwitterの影響力が比較的大きい高校なんじゃないでしょうか。前に誰かが「NSGの文化祭は実質オフ会。むしろ毎日オフ会。」みたいなことを言っていたりもしました。

 その事実自体に良い悪いはないですし、楽しいことも多いと思います。実際私には会ったこともないNSG生の知り合いがたくさんいますし、そのヒト達とはTwitter上で出会いました。

 が、楽しさの反面非常にリスキーです。とある一年生は青姦現場を撮影されまたたく間に拡散され、その相手の女の子はTwitter上で3年情報科に盛大に喧嘩を売ったりしていましたし(アルパカの分際で)。とある三年生は元カノのふとももを舐めている動画が拡散されていました、僕だったら自殺もんです。生徒会長候補だったとある二年生は、授業中の態度を撮影され晒され、拡散され、一人だけ極端に少ない票数で、結局落選した。という話もありました。

 Twitterは楽しいですが、インターネット・リテラシーを守って他人を傷つけない、傷つけられないようボロを出さないことを徹底しないと、特に新座総合に通う人たちは痛い目をみる可能性が比較的高いといえます。

馬鹿

 僕は、僕の知っている新座総合の生徒の大半は色々な意味で馬鹿だと思っています。

 一口に馬鹿といっても色々な種類があるのですが、まず1つめは純粋な知能の低さというか理解力のなさです。よく僕とつるんでいる連中は単に勉強に興味がなかったり、情報技術に強い興味があったりして新座総合にいるので、それを感じることはまずないのですが、一部の生徒と会話してる時に、「こいつ、マジで日本語が話せないんじゃなかろうか。」と思うことがあります。僕の通っている学校は偏差値60前後の学校で、特に頭が良いというわけではないですが、ありえないくらい理解力がない、みたいな生徒はほとんどいないと思います。実際僕は会ったことがありません。ですが、新座総合くらいだと、稀に本当に日本語を理解できない生徒がいるようで、会話が成り立ちません。しんどいです。

 2つめは、愚直というか、悪い意味で素直というか、教室で肉を切ったり焼いたりすることです。教室で焼肉をするのがなぜいけないのか、よく考えると、論理的に否定することが結構難しいです。校則と照らし合わせて考えても、(彼らはここを怠ったため摘発されたが)「火器を使用しない」「刃物を使用しない」を守れば、教室内焼肉はやっていいことになります。ですが、常識的に考えてありえません。おそらく、普通の人間なら頭の中の常識が教室で焼肉をやりたい意思のストッパーとなり、実行に移すものはほとんどいないでしょう。もちろん、赤信号みんなで渡れば怖くない精神的なものはあったのでしょうが、それにしたって意味がわかりません。もう一つ、そういった例をあげるとすれば、彼らの一部は会って一ヶ月も経たない僕の学生証をビリビリに引き裂いたこともあります。別に学生証はくっつければいいので、ある程度は破られてもいいのですが、これも常識的に考えてありえません。「相手の機嫌を損ねず、リカバリーの効く範囲内(彼らが意図的にこの範囲内におさめたのかは定かではないが)」でやっているので、特に問題ではないのですが、常識的に考えて、あって間もない人間の身分証明証を破くのは意味がわかりません。お詫びといってその一年後にオ◯ホールを渡してきたのもなおさら意味がわかりません。

最後に

 世の中には変な人間が偶然同じ学校に集まってしまうことがあるということです。今の3年生は間違いなく、変です。学校内で変とかそういうレベルではなく、社会的に変な人間が数名います。彼らからは色々なことを学ぶことができますが、敵に回すと面倒臭いことこの上ありません。彼らと関わりを持つ時は慎重になるべきです。気づいたらその一員になっていた、なんてことがあるかもしれません。

 随分ひどいことを言いましたが、彼らと出会えていい意味で人生が変わったと思っています。先程の焼肉や学生証の件もそうですが、彼らは常識に囚われない行動力があります。一人ではやろうと思わないことも彼らといると気づいたらやっていたりします。そのせいで校内不法侵入等を犯してしまったこともありましたが、良い方向にも転がることがあるということです。そしてなにより一緒にいて楽しいです。彼らのような人間は滅多にいないと思いますが、もしこれを読んだ方の目の前に、会って間もなく身分証明証を破いてくる奴が現れたら、とりあえず一緒にいればなんだかんだおもしろいことになるとは思いますよ。

kotlin/JSがどんなもんなのか調べてみる①

いつかのkotlinブログで言及されていた話ですが、日本でこれに言及している人あまりいないのではと思ったのでとりあえず日本語にして、英語をわざわざ読むほどではないが、KotlinのJSコンパイルに興味があるという日本人が読んでくれることを願います。


kotlin1.1では、kotlinのJavaScriptコンパイル機能が、正式にリリース可能な段階に達しました。もちろん、コンパイラのサポートは実生活の問題を解決するレベルではないので、私達はkotlinをより大きなJavaScriptエコシステムに統合する作業を続けていきます。

今回は、Kotlinとnpmとwebpackとkarmaを統合したGradleプラグインと、Kotlin/JVMで書かれたバックエンドとReactを使ったKotlin/JSのフロントエンドのフルスタックアプリケーションのサンプルの2つのプロジェクトを紹介します。

Koltin Frontend Plugin

kotlinフロントエンドプラグインを使用すると、webpackを使用してkotlinフロントエンドアプリケーションをビルドしてデプロイすることができます。アプリケーションの依存関係にnpmパッケージを使用することが可能です。このプラグインはそれらをダウンロードし、JSファイルにバンドルします。このプラグインはkarmaと統合されていて、アプリケーションのテストを実行することもできます。また、最適なワークフローのために、このプラグインは継続的コンパイルとホットリロードをサポートしているため、常に最新のバージョンのアプリケーションをブラウザに表示しておくことができます。

READMEファイルプラグインの使用方法が記載されています。exampleディレクトリには、実際のプロジェクトでどのように適用されるかの簡単な例があります。

Kotlin React Example

Thinkerは、kotlinに組み込まれた最新のフルスタックアプリケーションの1つの例です。バックエンドはJettyで動作し、Kotlin開発チームによって開発されたKotlin webアプリケーション開発フレームワークKotrを使用しています。フロントエンドはReactを使用します。プロジェクトの一環としてKotlin用のReactラッパーセットが提供されています。プロジェクトのラッパーを使うことで、自分の用途に合わせてラッパーを使用することができます。私達はまだReactラッパーを内部で開発していることに注意してください。そして、そのReactラッパーを別のOSSライブラリとして提供することを検討しています。(@tako_programing<まだ提供されていないみたいだったので、https://github.com/sosukesuzuki/kotlin-react に該当箇所のみforkしました)

React Kotlinのコードがどのように書かれるのかは、thinkerで使われているコンポーネントを見ることで知ることができます。

これらのリリースに関する意見を歓迎しております。GtihubでIssueを出したり、フォーラムでストップしたり、Kotlin Slackの#javascriptチャンネルに参加したりしてください!


ということらしいですね、暇な時にフロントエンドプラグインを使ってみてまたブログでも書こうかなあと思います

react製webアプリでショートカットを実装するときはkeymasterを使うと便利かもしれない

こんにちは。眠み卍。tako_programingです。 次の記事でmarkdownを抽象構文木でいじる話をしますみたいなことを言った気がしますが、keymasterが便利だったので、まずショートカットキーの話をします。 Slackとかみたいなwebアプリってショートカットキーがあって便利じゃないですか。アレ実装したいなぁと思ったんですが、1から実装すると普通に面倒なので、いい感じなライブラリを使いたいなぁとなります。で、まあ探していくと結構たくさんあってreact-shortcutsとかreact-hotkeysとか色々ありますが、star数がその中でダントツで多く、使い方が非常にシンプルでわかりやすかったので、masterkeyを採用しました。基本的にリポジトリのREADMEに書いてある通りにやればなんの問題もなくできますが、一通りの使い方とreactでやる上で3秒くらいハマった箇所を紹介します。

使い方

インストールします。

npm insttall --save keymaster

使いたい箇所でimportします

import key from 'keymaster'

いい感じな場所(自分はconstructorでやりました。)でショートカットを定義します。

key('a', function() {alert('you pushed a')})

こうするとaを押すと「you pushed a」とアラートが出ます。便利。まあcommandやoptionなんかと組み合わせたショートカットを作りたい場合が大半だと思いますので、そういう時は

key('option+a' function() {alert('option + a!!!')})

文字列で'option+a'を指定すれば問題なく期待どおりの動作をします(が、ブラウザやOSのショートカットとの衝突にお気をつけください)。

reactで使う時の話

僕は完全にフィーリングプログラマーなので、最初ショートカットをおした時にsetStateさせたかったので、こんなコードを書きました。

key('option+a' function() {this.setState({hoge: "aaa"})})

これだときちんと動作しなくて、hogeがundefinedと言われます。なんならthis.setStateがundefinedです。console.logでthisを吐かせればわかりますが、thisがkeyを参照しているので当たり前ですね。
期待どおりの動作をするコードはこちらです。

key('option+a', this.handleEnterOptionA.bind(this))
handleEnterOptionA() {
  this.setState({hoge: "aaa"})
}

関数を別途定義して引数に渡してあげるといい感じに思った通りに動きます。

reactでmarkdownする時はremarkを使うといいよという話01

こんにちは。学校が夏休みに突入し、うかれているtako_programingです。実は最近10hzというマークダウンをチーム内で共有するwebサービスの開発に携わらせてもらってるんですが、その中でmarkdownの処理の所を任されて1から書くとひどいことになる気がしたのでいろんなライブラリを駆使してやることにしました。

導入で詰まったところ

開発の最初の頃はreact-markdownを使ってマークダウンのプレビューをしていたみたいで、これはこれで便利ではあるのですが、このライブラリはcommon markに準拠していて、僕らはGFM(GitHub Flavored Markdown)でプレビューしたかったので、remark-reactに変更しました。このライブラリはcommon markでもプレビューできるしGFMでもプレビューできる優れもので、即採用することに決めました。 採用することを決めたのはいいんですが、remark-parseのリポジトリのREADME通りに書くと、GFMのtaskListが表示されません。

var React = require('react'),
    remark = require('remark'),
    reactRenderer = require('remark-react');

var App = React.createClass({
    getInitialState() {
        return { text: '- [ ] aaa¥n- [ ] bbb¥n- [ ] ccc' };
    },
    onChange(e) {
        this.setState({ text: e.target.value });
    },
    render() {
        return (<div>
            <textarea
                value={this.state.text}
                onChange={this.onChange} />
            <div id='preview'>
                {remark().use(reactRenderer).processSync(this.state.text).contents}
            </div>
        </div>);
    }
});

React.render(<App />, document.getElementById('app'));

こんなふうに書いても実際のプレビュー画面では通常のリストのように表示されます。READMEには「デフォルトでGFMモードです」みたいなことが書いてあったのでおかしいぞ?となって良いことではないのかもしれませんが急いでいて時間もなかったのでリポジトリにIssueで質問した所「optionでsanitizeをfalseにするんだよ!!」と懇切丁寧に教えていただき、

<div id='preview'>
    {remark().use(reactRenderer, { sanitize: false }).processSync(this.state.text).contents}
</div>

のように書き換えることで、Tasklistが表示されるようになりました。ありがたい。 ですが、ほっとしたのもつかの間、次の敵「コードブロックのシンタックスハイライト」が現れました。デフォルトのままではコードブロックにシンタックスハイライトがつかないんですが、放置するわけにもいかないのでシンタックスハイライトに対応させることにしました。 リポジトリのREADMEでシンタックスハイライト用に紹介されているのはremark-react-lowlightですが、こちらの環境が悪いのか挙動がすこぶる不安定で他の方法を探すことにしました。remark-reactでは、

remarkReactComponents: {
  a: MyLink,
  p: MyParagraph
}

のようにして指定したタグを指定したReactComponentで置き換えることができます。なので、codeタグの所をいい感じのシンタックスハイライトがつくコンポーネントで置き換えればいいのではないかと思い試してみました。 最初はmarkdownエディタの方で使っているreact-codemirrorを試しましたが、こちらも(結構前のことなので詳しく覚えてないが)不安定というか描画がなんか明らかにおかしくなってしまい採用を断念しました。いま挙げた2つのライブラリもどうにかすればちゃんと使えるのだとは思いますが、そこに時間をかけたくなかったのでもう少しなにもしなくても使えるライブラリを探すことにしました。で、最終的に今使っているのがreact-hilightです。なので最終的には

{remark().use(reactRenderer, {
     sanitize: false,
     remarkReactComponents: {
         code: react-highlight
    }
 }).processSync(this.state.content.content).contents}

という感じになりました。react-hilightを使う時はhilight.jsをimportするのを忘れないようにしてください。


これでとりあえずはreact-remarkをつかってマークダウンを描画することができるようになりました。ですが、このままだとtaskListにチェックしても参照先のmarkdownのテキストにはチェックが入らないという問題が発生します。これの解決策はまた次の記事で。

playのHTTP routingをクソ和訳

完全な自分用メモです。翻訳がおかしければ最終的な日本語もおかしいHTTP routingの和訳です。


ビルトインHTTPルーター

このルーターは、各HTTPリクエストをActionに変換する役割を果たすコンポーネントです。

HTTPリクエストはMVCフレームワークで、イベントとして認識されます。イベントには以下の2つの主要な情報が含まれています。

  • (e.g. /clients/1542, /photos/list)のようなクエリ文字列を含むリクエストパス

  • (e.g. GET, POST, …)のようなHTTPメソッド

ルーティングは、conf/routesファイルで定義されコンパイルされます。つまり、ブラウザ上にそのままエラーが表示されます。

Dependency Injection(依存性の注入)

playでは二種類のルーターの生成をサポートしています。1つは依存性注入ルータ、もう1つは静的ルーターです。標準では依存性注入ルーターが使われます。playでは依存性注入コントローラーを使用することを推奨していますので、Activatorのテンプレートでも依存性注入コントローラーを使用するようになっています。静的コントローラを使用する必要がある場合は、build.sbtに以下のように記述します。

routesGenerator := StaticRoutesGenerator

playのドキュメントのコードサンプルは、注入されたルータージェネレーターを使用することを前提としています。これを使用しない時は、ルートコントローラの呼び出しの先頭部に@シンボルをつけたり、各コントローラをclassではなくobjectとして宣言することで静的ルートジェネレータに自由に変更することが可能です。

ルーティングファイルの文法

conf/routeは、ルーティングに使用される設定ファイルです。このファイルには、playアプリケーションの全てのルートが一覧で表示されます。各ルートはHTTPメソッドとURIパターンで構成され、どちらもActionジェネレータへの呼び出しに関連付けれらます。

ルート定義は次のように記述します。:

GET   /clients/:id          controllers.Clients.show(id: Long)

ルートはHTTPメソッドで初まり、その後にURIパターンが続きます。最後の要素は呼び出し定義です。

また、ルートファイルには、#シンボルから始まる文字列でコメントを追加することができます。

# Display a client.
GET   /clients/:id          controllers.Clients.show(id: Long)

特定のプレフィックスの下にある別のルータを使用するには->の後ろに与えられた接頭辞を使用します。

->      /api                        api.MyRouter

この方法は、SIRDルーティングとも呼ばれるString Interpolationg Routing DSLと組み合わせたり、複数のルートファイルを使用してルーティングするSub Projectを処理する場合に便利です。

HTTPメソッド

HTTPメソッドは、HTTP(GETPATCHPOSTPUTDELETEHEAD)で、サポートされている有効なメソッドのうちどれでも構いません。

URIパターン

URIパターンはルートのリクエストパスを定義します。リクエストパスの一部は動的であっても構いません。

静的なパス

たとえば、GET /clients/allリクエストに対応させるためには、次のようなルートを定義します。

GET   /clients/all          controllers.Clients.list()

動的なパス

IDでクライアントを取得するようなルートを定義する場合は、動的なパーツを追加する必要があります。

GET   /clients/:id          controllers.Clients.show(id: Long)

注: URIパターンは複数の動的部分を持つこともできます。

動的部分のデフォルトのマッチングでは、正規表現[^/]+で定義されます。つまり,:idで定義された動的部分は、正確に1つのURIパスセグメントに一致します。他のパターンタイプとは異なり、パスセグメントはルートに自動的にURIデコードされた後、コントローラに渡され、逆ルートでエンコードされます。

複数の動的部分 /

動的部分が複数のURIパスセグメントをスラッシュで区切って取得するようにするには、*id構文(ワイルドカードパターンとも呼ばれる*id正規表現を使用すます。)を使って動的パターンを定義できます。

GET   /files/*name          controllers.Application.download(name)

GET /files/images/logo.pngのようなリクエストの場合、動的部分nameimages/logo.pngを取得します。

複数の/にまたがる動的部分は、ルータによってデコードされないまたは、逆ルータによってエンコードされることに注意する必要があります。生のURIセグメントを検証するのはあなたの責任です。逆ルータは文字列の連結のみを行うため、結果のパスが有効であることを確認する必要があります。例えば、複数のスラッシュやASCII以外の文字は含まれません。

動的部分にカスタム正規表現を使用する

$id <regex>構文を用いて動的部分に独自の正規表現を定義することができます。

GET   /items/$id<[0-9]+>    controllers.Items.show(id: Long)

ワイルドカードのルーティングと同様に、パターメタはルーターによっってデコードされないまたは、逆ルーターによってエンコードされません。それが正しいかどうかを検証する必要があります。

ActionGeneratorメソッドの呼び出し

ルートの定義に最後の部分はActionGeneratorメソッドの呼び出しです。この部分では、play.api.mvc.Action型の値を返すメソッドへの有効な呼び出しを定義する必要があります。これは通常、ControllerのActionメソッドになります。 メソッドがパラメータを定義していない場合は、メソッドの完全修飾名を指定してください。

GET   /                     controllers.Application.homePage()

Actionメソッドが1つ以上のパラメータを定義する場合、これらのパラメータはすべてリクエストURI、またはクエリ文字列から検索されます。

# Extract the page parameter from the path.
GET   /:page                controllers.Application.show(page)

または、

# Extract the page parameter from the query string.
GET   /                     controllers.Application.show(page)

下に、対応するControllerのめメソッド定義を示します。

def show(page: String) = Action {
  loadContentFromDatabase(page).map { htmlContent =>
    Ok(htmlContent).as("text/html")
  }.getOrElse(NotFound)
}

### パラメータの型 ルート定義にあるActionGeneratorメソッドの引数がString型の場合、型を明示する必要はありません。ですが、playでリクエストパラメータを他の特定のScalaタイプにする必要がある場合は、引数の型を明示する必要があります。 scala GET /clients/:id controllers.Clients.show(id: Long) また、Controllerの対応するshowメソッドの定義でも同様に型を明示する必要があります。 scala def show(id: Long) = Action { Client.findById(id).map { client => Ok(views.html.Clients.display(client)) }.getOrElse(NotFound) } ### パラメータの値の固定 リクエストパラメータに値が存在しない場合に使用するデフォルトの値を設定することもできます。 scala # Pagination links, like /clients?page=3 GET /clients controllers.Clients.list(page: Int ?= 1) ### オプションパラメータ 全てのリクエストに対して必ずしも必要とは限らないオプションのパラメータを指定することも可能です。

# The version parameter is optional. E.g. /api/list-all?version=3.0
GET   /api/list-all         controllers.Api.list(version: Option[String])

ローティングの優先順位

多くのルーティング定義がたくさんのリクエストに合致してしまう場合が存在します。その場合は、宣言順で使用されます。

逆ルーティング

ルーターは、逆にScalaプログラムからURLを生成するためにも使うことができます。この機能によって全てのURIパターンを単一の設定ファイルに集中させられるので、リファクタリングが楽になります。

ルーターはルートファイルで使用される各Controllerに対し、routesパッケージ内にreverse controllerを生成します。これは、ルートファイルで使われるメソッドと同一のシグネチャを持ちますが、play.api.mvc.Actionではなくplay.api.mvc.Callを返します。

たとえば、下のようなControllerを定義したとします。

package controllers

import play.api._
import play.api.mvc._

class Application extends Controller {

  def hello(name: String) = Action {
    Ok("Hello " + name + "!")
  }

}

これに対応するようにconf/routesにルーティングを記述すると

# Hello action
GET   /hello/:name          controllers.Application.hello(name)

次に以下のようにして、controller.routes.Applicationリバースコントローラーを使って、helloアクションメソッドを使うことができます。

// Redirect to /hello/Bob
def helloBob = Action {
  Redirect(routes.Application.hello("Bob"))
}

注: 各コントローラにはroutesサブパッケージが存在します。そのため、コントローラcontrollers.admin.Application.helloアクションは、controllers.admin.routes.Application.hello(ルートファイルconf/routesに、Scalaプログラム内の逆ルーティングで生成されたパスと一致する他のルートがない場合に限り)逆ルーティングを行うことが可能です。

Scalaプログラム内から呼ばれた逆Actionメソッドはとても単純に機能します。このメソッドは、パラメータをとり、ルートパターンに戻します。パスセグメント(:fooのような形をしたもの)は、値は実際に置き換えが行われる前の時点でエンコードされます。正規表現ワイルドカードを用いたルーティングパターンの場合は、値が複数のセグメントにまたがる可能性があります。そのため、そのような値を逆ルーティングに用いる場合には、必要に応じてこれらの値をエスケープして、未検証のユーザー入力を渡さないように注意してください。

デフォルトのコントローラ

playには、いくつかの便利なActionが定義されているDefault Controllerが含まれています。これらはルートファイルconf/routesから直接呼び出すことが可能です。

# Redirects to https://www.playframework.com/ with 303 See Other
GET   /about      controllers.Default.redirect(to = "https://www.playframework.com/")

# Responds with 404 Not Found
GET   /orders     controllers.Default.notFound

# Responds with 500 Internal Server Error
GET   /clients    controllers.Default.error

# Responds with 501 Not Implemented
GET   /posts      controllers.Default.todo

上記の例では、GET /のリダイレクトで、外部サイトに飛ぶようになっていますが、別のアクション(例では/ postsなど)にリダイレクトすることも可能です。

カスタムルーティング

playには、String Interpolating Routing DSL、通称sirdと呼ばれる組み込みルータを定義するためのDSLを定義されています。このDSLには、軽量のplayサーバーの組み込み、通常のplayアプリケーションへの高度なルーティング機能の提供、テスト用RESTモックサーバーを作成するなどの用途に使用できます。

詳しくはString Interpolationg Routing DSL

playのActions, Controllers and Resultsをてきとうに和訳

実はplayロクに触ったことがないので、ちゃんと勉強してみようかなぁという試みです。


Actionって?

playアプリケーションの受け取るほとんどのリクエストは、Actionによって処理されます。play.api.mvc.Actionは、基本的にリクエストを処理し、クライアントに送信する結果を生成する(play.api.mvc.Request => play.api.mvc.Result)型の関数です。

def echo = Action { request =>
  Ok("Got request [" + request + "]")
}

Actionは、Webクライアントに送信するHTTPレスポンスを表すplay.api.mvc.Result値を返します。この例では、Okはtext/plainを含む200 Okレスポンスを生成します。

Actionの生成

play.api.mvc.Actionコンパニオンオブジェクトは、Action値を構築するためのヘルパーメソッドをいくつか提供します。

まず最初に紹介するのは、引数として、Resultを返す式ブロックを取ります。

Action {
  Ok("Hello world")
}

これはActionを作成する最も簡単な方法ですが、受け取ったrequestへの参照がありません。このActionを呼び出すHTTPリクエストにアクセスすると便利なことがよくあります。 そのため、引数としてRequest => Resultをとる別のActionビルダーが存在します。

Action { request =>
  Ok("Got request [" + request + "]")
}

implicitキーワードを用いて、リクエストパラメータを暗黙的にマークすると、それを必要とする他のAPIによって暗黙的に使用されることがあります。

Action { implicit request =>
  Ok("Got request [" + request + "]")
}

最後に紹介するActionビルダーは、追加のBodyParserを指定するものです。

Action(parse.json) { implicit request =>
  Ok("Got request [" + request + "]")
}

BodyParserについての詳細はこのマニュアルの後半で説明します。今のところ、Action値を作成する他のメソッドはデフォルトのAny contetn body parserを使用していることを知っておいてください。

ControllerはActionを生成するオブジェクトです。

ControllerはAction値を生成するオブジェクトにすぎません。Controllerは、Dpendency Injenctionを利用するクラスとして定義することも、オブジェクトとして利用することもできます。 注:Controllerをobjectとして定義することは、playでは将来的にサポートされなくなります。クラスでのControllerの使用が推奨されます。 Action値のジェネレータを定義する最も簡単な方法は、Action値を返す、引数を持たないメソッドです。

package controllers

import play.api.mvc._

class Application extends Controller {

  def index = Action {
    Ok("It works!")
  }

}

もちろん、Actionジェネレータメソッドは引数を持つことも可能であり、これらの引数はクロージャとして使うことができます。

def hello(name: String) = Action {
  Ok("Hello " + name)
}

シンプルなresults

いまのところ私達は、ステータスコードなどのHTTPレスポンス、HTTPヘッダーのセット、およびWebクライアントに送信される文章などのシンプルな結果に興味があります。これらのシンプルな結果はplay.api.mvc.Resultによって定義されています。

import play.api.http.HttpEntity

def index = Action {
  Result(
    header = ResponseHeader(200, Map.empty),
    body = HttpEntity.Strict(ByteString("Hello world!"), Some("text/plain"))
  )
}

もちろん、上記のサンプルでOkのResultのような一般的な結果を作成するためのヘルパーがいくつか存在します。

さまざまな結果を表示するためのいくつかの例を下に示します。

val ok = Ok("Hello world!")
val notFound = NotFound
val pageNotFound = NotFound(<h1>Page not found</h1>)
val badRequest = BadRequest(views.html.form(formWithErrors))
val oops = InternalServerError("Oops")
val anyStatus = Status(488)("Strange response type")

なお、これらのヘルパーはすべてplay.api.mvc.Resultsのトレイトとコンパニオンオブジェクトに定義されています。

リダイレクトもシンプルなresultsです。

ブラウザを新しいURLにリダイレクトすることは、種類のことなるシンプルなresultsに過ぎません。ただ、これらの結果はリクエストボディを使用しません。 リダイレクトのためのResultを作成するには、いくつかのヘルパーが利用できます。

def index = Action {
  Redirect("/user/home")
}

標準のままだと、303 SEE_OTHERレスポンスタイプを使用しますが、必要に応じてより具体的なステータスコードを設定することができます。

def index = Action {
  Redirect("/user/home", MOVED_PERMANENTLY)
}

TODO ダミーページ

TODOとして定義された空のAction実装を使用することが可能です。そのresultは標準のNot implemented yetのページになります。

def index(name:String) = TODO