技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

Polymer1.0 の入門を始める

Polymer ってなんぞ?

What is Polymer? - Polymer

Custom elements extend the web

一言でビルトイン以外のカスタムタグを追加すると。
カスタムなイベントや、デフォルトのスタイルも含めてコンポーネントとして定義できるらしい。

面白いのは「フレームワーク」とは名乗ってない所か。HTML5とか勉強会で聞いた通りだ。

ソースを読む

Polymer の導入そのものは、bower さえ入ってれば速攻できるらしい。 Get the code - Polymer
簡単なことはいいことだ。

その上でコンポーネント製作テンプレートを眺めてみた。

Create a reusable element - Polymer

結構いろいろ入ってるが、コンポーネントを作って GitHub で共有するところまであるらしい。
テンプレートを見る限り、基本的にテストも含む全件が入っていそうな感じだ。

Play で導入するなら、画面切り離しでサブプロジェクトでコンポーネントを作ってアクセスするのが良さそうに見える。

後でやってみよう。

ドキュメントを読んでみる

Quick tour of Polymer - Polymer

そして先ほども思ったが、非常にシンプルに作れるっぽい。
コンポーネント製作部分。下記の例だと、proto-element というタグを定義(ファイル名もproto-element"

<link rel="import"
      href="bower_components/polymer/polymer.html">

<script>
  // register a new element called proto-element
  Polymer({
    is: "proto-element",
    // add a callback to the element's prototype
    ready: function() {
      this.textContent = "I'm a proto-element. Check out my prototype!"
    }
  });
</script>

このコンポーネントはどうも JavaScript 上の運用もできる模様。Registration and lifecycle - Polymer

既存のタグを継承して作ることもできる。

MyInput = Polymer({

  is: 'my-input',

  extends: 'input',

  created: function() {
    this.style.border = '1px solid red';
  }

});

var el1 = new MyInput();
console.log(el1 instanceof HTMLInputElement); // true

var el2 = document.createElement('input', 'my-input');
console.log(el2 instanceof HTMLInputElement); // true

作ったコンポーネントは、is 属性を使って既存タグに適用することもできる

<input is="my-input">

ライフサイクルについても読んでみた

順序別配置。

  • created: 初期化後に呼ばれるイベントハンドラ
  • (ローカルDOM作成)
  • ready: DOM が作成されたタイミングでコールされるイベントハンドラ
  • factoryImpl: コンストラクタ
    ただし、HTML上にタグとして定義した場合は動作しない。
  • attached: 見たまま。利用可能になった際のイベント。

また、この後に、以下の事が書かれてる。

  • create は必ず ready 前に実行される
  • ready は必ず attached の前に実行される
  • ready は子要素から順に呼ばれる

残りのイベントハンドラ

  • detached: 見たまま。画面から外された時だと思われ
  • attributeChanged: 見たまま、属性変更時。
var MyElement = Polymer.Class({

  is: 'my-element',

  // See below for lifecycle callbacks
  created: function() {
    this.textContent = 'My element!';
  }

});

document.registerElement('my-element', MyElement);

// Equivalent:
var el1 = new MyElement();
var el2 = document.createElement('my-element');

後は、registerElement でタグを定義して、 createElement で貼り付けができるらしい。

とりあえず、初回導入とコンポーネント追加以外では bower 要らなそうなので、Play にもそのまま組み込めると思われ。

Playframework2.4.xのサブプロジェクトの扱い

完全に親子関係でしたねってだけ。

  • 子のオブジェクトは親から参照できるけど、親のオブジェクトを子は参照できない。
  • 同時に、子は横つながりを持たない。

まぁなんとなく想像通りな訳で、使い道的には、幾つかのプロジェクトで共有しておきたい機能をサブプロジェクトに置いて、別リポジトリ管理しておくという使い道が考えられるか。
バッチサーバーを後々考えている場合、モデルをサブプロジェクトに分離しておくのは良い手だと思う。

URL 切り離しできる機能については、使い道が無いとは言わないがこの関係だと使いどころに悩む。

それぞれ独立した REST API をサブプロジェクトに切り離す…ということも考えなくはない。
むしろそういう用途を考えて設計している気がする。

駄文

まずはじめに最近好きな言語を挙げるが、Scala / F# なんかが好きだ。
そのどれもに共通することを挙げよう。

  • 静的型
    型があれば、おかしなコードはコンパイルで弾ける。
    規約の準拠チェックもツール作りが動的型よりは容易だ。
  • 関数型
    関数が引数や返り値にできることで、共通化や抽象化に関してアドバンテージを持つ。
    何より副作用、わかりやすいところで変数が一気に減る(関数型はそういうところを重視する)。
    結局オブジェクトが状態変化をすると、状態に依存したコードを皆書いてバグにしてしまうのだ。
    ならば、状態が無ければいい。当然の帰結である。

という点で一致している。
好きではないが、それでもよく使うのは Coffee だろうか?

結局、プログラマとはコードを書いてお金をもらう職業である。
そして、やってれば直ぐに分かるのだが、作って納めたらはい終了というアプリケーションは実のところ少ない。
すると気にしなければならないのがメンテナンスコストだ。
現実問題、拡張や修正で開発期間の数倍続く事が多い。アジャイル開発なんてもろに保守だけで開発を進める様式に等しい。

分かってる人が少数精鋭で作る場合は動的型の方が圧倒的生産性を誇る(RoR)。ここに疑いの余地はないと思う。
しかしそんな精鋭と一緒に仕事できる機会がどれだけあるよって話はある。

かといって、Java7以前 + Struts2 なんて環境で開発効率が上がる訳がない。

そういうことだ。

そして、そうした関数型の言語機能が最近、C++/Java なんかにまで取り入れられている。
何が言いたいかというとだ。

もうパラダイムシフトが始まってる

2 年前の LL 祭りで Matz さん(Ruby開発者)が言った通りの進化である。

皆でカリー(currying)食べて食料(人・コード量的リソース)問題を緩和させよう!

(23:34)ふと思い出したので追記。良く良く考えたら、6年前に札幌の勉強会で、札幌で「もう次のパラダイムシフトの目は出てる」と sumimさんが言ってたよーな。その頃は CLR/H 勉強会で、C#3.0 な話(この時は正式版ではなかった)の話で盛り上がってた時期だったと思う。
温故知新ではないですが、確かに既にある技術や、埋もれた過去の技術の中に、次のパラダイムシフトのヒントはいつだってありますよね…。

PlayFramework 2.4 でサブプロジェクトで一部URLを切り出してみる

教科書は下記

SBTSubProjects

で、まずはプロジェクト root ディレクトリに下記を一気に作成

  • modules
    • /rest_apis
      • /controllers
      • /conf

そして、

modules/rest_apis/build.sbt を作成する。

ここに実は二つ罠があった。
公式では下記(20015/7/8 時点)が書かれているのだが

name := "myadmin"

libraryDependencies ++= Seq(
  "mysql" % "mysql-connector-java" % "5.1.35",
  jdbc,
  anorm
)

ここに罠が二つあって、

  1. Play2.4 では anorm が分離したので、書き方が違う
  2. scalaVersion := "2.11.6" などのように、ScalaVersion を親と同じ指定をしないと、ビルドでこける(下記)
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  ::          UNRESOLVED DEPENDENCIES         ::
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn]  :: rest_apis#rest_apis_2.11;0.1-SNAPSHOT: not found
[warn]  ::::::::::::::::::::::::::::::::::::::::::::::
[warn] 
[warn]  Note: Unresolved dependencies path:
[warn]          rest_apis:rest_apis_2.11:0.1-SNAPSHOT
[warn]            +- a-albums:a-albums_2.11:1.0-SNAPSHOT
[trace] Stack trace suppressed: run last root/*:update for the full output.
[error] (root/*:update) sbt.ResolveException: unresolved dependency: rest_apis#rest_apis_2.11;0.1-SNAPSHOT: not found
[error] Total time: 5 s, completed 2015/07/08 21:42:26

自分は、とりあえず切り離しが目標だったので、anorm の記述は削除して、ScalaVersion は2.11.6 を指定した。

name := "rest_apis"

scalaVersion := "2.11.6"

libraryDependencies ++= Seq(
  "mysql" % "mysql-connector-java" % "5.1.35",
  jdbc
)
続きを読む

Play 2.4.x をいい加減調べてみる

色々変わったそうなので、まずはハイライトを見てみる。

https://www.playframework.com/documentation/2.4.x/Highlights24

  • DI サポート
    • テストにおけるモックを容易にしたかった
    • 軽量な組み込みPlayアプリケーションや、一つのJVM上で複数のPlayアプリケーションを立ち上げるなど、インジェクションを利用したより面白そうなことがしたかった
    • 下記の理由により、アプリケーションライフサイクルが容易に追っかけられるようにしたかった

Removing Play’s global state is however a big task that will require some disruptive changes to the way Play applications are written. The approach we are taking to do this is to do as much as possible in Play 2.4 while maintaining backwards compatibility. For a time, many of Play’s APIs will support both methods that rely on require global state and methods that don’t rely on global state, allowing you to migrate your application to not depend on global state incrementally, rather than all at once when you uprgade to Play 2.4.

Play のグローバル・ステートの取り除きは、既に書かれたアプリケーションに対して破壊的な変更を加えるようなビックタスクの一つです。このアプローチを後方互換性を維持しつつ行うために、Play2.4 の実装を行っています。Play2.4では、多くのPlay APIでグローバル・ステートに頼るメソッドと、グローバル・ステートに頼らないメソッドをサポートしており、グローバル・ステートに頼らないマイグレート手段を提供することになります。

The first step to removing global state is to make it such that Play components have their dependencies provided to them, rather than looking them up statically. This means providing out of the box support for dependency injection.

そのファーストステップとして、静的な依存をするよりも、依存を外から供給されるようなモデルで Play components を作った。つまりDIのサポートによる、ボックス外からの依存供給だ。

訳合ってる自信はないが、ニュアンスはこんな感じだと思う。

アプローチは、

最後のは Scaler の人だけの恩恵か?Java で Cake とか返って面倒そうな…。

テストが大幅に変わった。 ScalaTestingWithGuice

なるほどDIによる依存切り離しを実にそのまま実装してるね。

ScalaTestingWithDatabases DB テストの書き方も変更になったし、Evolution を切り離したところもそうだけど、テスト中での Evolution/カスタムEvolution にも対応したと。

ScalaTestingWebServiceClients ダミーサーバを作ってのテストもかなり容易になった。ダミー応答もリソースの中に置いとける。

アプケーション内での組み込みサーバ とかいい意味で気持ち悪い。

サブプロジェクト間で、リバースルーティングに対応 AggregatingReverseRouters

Anorm 切り離し。Ebean 切り離し(Scala-ActiveRecord ばっか使ってたから気づかなかった…)。HikariCP Support(なんか勝手に使ってた…すまん。WS のHTTPSでのSNIサポート。

実験的サポートで、Akka HTTP support、Reactive Streams Support(非同期ストリーミング処理フレームワークの一種。JSR にしてやるって頑張ってる)と。
個人的に Akka HTTP はスッゲー気になるけど、試験サポートだからちょっと放置。

まずは使い慣れるのが先と。

サブプロジェクト間でリバースルーティングができるというのは非常に気になる。
サンプルでも載ってたけど、Web インターフェースと REST API を切り離すということができそう。

AmazonEC2 上に、Redmine 2.6.5 + Backlogs (カスタム)を入れた

AMI 公開

AMI ID : ami-6465ca64

※ AMI 削除しました。

元ネタ

white-azalea.hatenablog.jp

カスタムBacklogs

github.com

本家が更新停止してるので、fork の中から最近までメンテされている物を使わせていただきました。

他の人も言及してるけど、リリース計画とロードマップの住み分けが今ひとつよくわかりませぬ…

本当は下記を入れたかったのだけど、Light のライセンス規約 Number of sites : 1 に抵触するかもしれないので断念。

Professional Redmine plugins: Agile, CRM, Helpdesk, Invoices, Finances. Redmine Themes and Services - RedmineUP

Redmine2.6.5 に Backlogs を突っ込んだメモ

事のついでだし、RedmineBacklogs を S3 + Redmine2.6.5 に入れようとしたログ。

元ネタの AMI はこれ

white-azalea.hatenablog.jp

まずは plugins ディレクトリで git clone git://github.com/backlogs/redmine_backlogs.git して、 cd redmine_backlogs/ から git tag でバージョンを見る。

...中略
v1.0.4
v1.0.5
v1.0.6

なので、git checkout v1.0.6 を実行。
最新のリリースバージョンに指定しておく。

その後、Redmine ルートで bundle exec rake db:migrate を始めるのだが、早速うまくいかない。

Could not find gem 'icalendar (>= 0) ruby' in any of the gem sources listed in your Gemfile or available on this machine.
Run `bundle install` to install missing gems.

bundle install しれというので、やってみる

$ bundle install --without development test
Don't run Bundler as root. Bundler can ask for sudo if it is needed, and installing your bundle as root will break this application for all non-root users on this machine.
Warning: this Gemfile contains multiple primary sources. Using `source` more than once without a block is a security risk, and may result in installing unexpected gems. To resolve this warning, use a block to indicate which gems should come from the secondary source. To upgrade this warning to an error, run `bundle config disable_multisource true`.
Fetching gem metadata from https://rubygems.org/.......
Fetching version metadata from https://rubygems.org/...
Fetching dependency metadata from https://rubygems.org/..
You have requested:
  nokogiri < 1.6.0

The bundle currently has nokogiri locked at 1.6.6.2.
Try running `bundle update nokogiri`

「nokogiri のバージョンが古いからだめぽ!」と言うので、bundle update nokogiri を打ってやる。
ちなみに、Nokogiri は HTML/XML とかのパーサー。

Installing nokogiri 1.5.11 (was 1.6.6.2) with native extensions

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

    /usr/bin/ruby2.0 extconf.rb
checking for libxml/parser.h... no
-----
libxml2 is missing.  please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies.
-----
以下略

はいはい

$ yum install libxml2 libxml2-devel

で?

checking for libxslt/xslt.h... no
-----
libxslt is missing.  please visit http://nokogiri.org/tutorials/installing_nokogiri.html for help with installing dependencies.
-----

またか…

yum install libxslt libxslt-devel

これでやっと nokogiri が入る。

bundle install がこれで越えられたので、bundle exec rake db:migrate を再度実行。
今度は問題なかった。

$ bundle exec rake tmp:cache:clear
$ bundle exec rake tmp:sessions:clear

を実行。キャッシュも削除する。

Backlogs をインストール

Redmine root ディレクトリに戻り、

$ bundle exec rake redmine:backlogs:install
rake aborted!
You must set the default issue priority in redmine prior to installing backlogs

rake 打つなら下準備しやがれと…公式ドキュメントに全く書かれていない事を要求される。
なんなんだ…。

で、ここでハマったのが「default issue priority」が何らかの Redmine プラグインの適用優先順みたいなものかと勘違いしてしまった事だ。
ここの内容は「Redmine のデフォルトでのチケット優先度を事前に設定してくれ」という事であり、admin で一旦ログインして設定を変更する必要があったわけだ。

この後は問題なくインストール完了。

後はプロジェクト作ったときに問題があれば下記を設定すれば良さそうだ。

http://yoshiyoshifujii.hatenablog.com/entry/2015/04/08/120124