UUUM攻殻機動隊

UUUMのエンジニアによる技術ブログです

【Rails】Rubyテンプレートで axlsx を出力する方法

ハローこんにちは、新人エンジニアのハトネコエです。

2016年10月22日発売の 『WEB+DB PRESS Vol.95』
UUUM のエンジニア達が書いた特集『試して学ぶHTTP』が載ります。よろしくお願いします。

WEB+DB PRESS Vol.95

WEB+DB PRESS Vol.95

  • 作者: 小出淳子,黒澤剛志,牧大輔,横江亮佑,山口貴也,尾藤正人,佐藤琢哉,中橋研太郎,田中慎司,小西裕介,伊藤直也,稲富駿,前島真一,長野雅広,山際康貴,のざきひろふみ,うらがみ,岡林大,遠藤雅伸,ひげぽん,海野弘成,はまちや2,竹原,大場寧子,大場光一郎,野々下裕子,WEB+DB PRESS編集部
  • 出版社/メーカー: 技術評論社
  • 発売日: 2016/10/22
  • メディア: 大型本
  • この商品を含むブログを見る

Rubyテンプレート

Rails4になってcsvが出力しやすくなった - Qiita

ここの記事にあるように、view テンプレートとして .ruby ファイルが使えるようになっています。
長くなりがちな CSV 出力の処理を controller 内でなく別ファイルに書けるので controller がすっきりしますね。

Excel 出力もこんなふうにしたい

Excel で表データを扱うことを前提にすると、CSV では、文字コードとか先頭に0を詰める出力がつらい。
CSV でなく Excel 用の .xlsx 形式で書き出したいよねーというわけで、
お世話になっているのが Axlsx という gem。

これで上記のような方法で controller と出力処理を分離しつつエクスポートする方法を探りました。

続きを読む

JSON型にindexも!MySQL 5.7のGenerated Columnsの可能性について探る

nazoです。

今回はMySQL 5.7の新機能であるGenerated Columnsについて紹介したいと思います。

Generated Columnsとは?

簡単に言うと、トリガーで特定のカラムにデータを入れるのを簡単に定義する方法みたいなもので、カラム定義時にAS 計算式と書くことで、そのカラムの値が該当の計算結果になります。

この機能はMySQL 5.7.6から追加されました。日本語では「生成列」と呼ぶこともあるようです。

続きを読む

BabelでES6で書いて、webpackでビルドして、mochaでテスト書いて、power-assertでassertの出力を見やすくして、karmaで複数ブラウザのテストを自動化して、カバレッジを出力するようにした

おはこんばんちは!! 尾藤 a.k.a. BTOです。

UUUMでは業務の効率改善に kintone を導入しようとしているのですが、kintone の機能を拡張するには Javascript でプログラムを書く必要があります。 そこで、Javascript の開発環境を構築したので、何をやったのかをまとめてみました。

具体的には、 BabelでES6で書いて、webpackでビルドして、mochaでテスト書いて、power-assertでassertの出力を見やすくして、karmaで複数ブラウザのテストを自動化して、カバレッジを出力するようにしました。 お前は何を言っているんだと思うかもしれませんが、僕も何を言っているのかわかりません。

Babel

言わずと知れた ES6 用のトランスパイルツールです。 ご存知の方も多いと思うので、詳細は割愛しますね。

Babel の導入は npm でインストールするだけ

% npm install babel babel-preset-es2015 --save-dev

babel-preset-es2015 は ES6(別名ES2015)用のプリセットです。 これでES6で記述できるようになります。

Babelは .babelrc というファイルがあると、その設定を読み込んでくれます。 ここに es2015 のプリセットを使用するように設定します。

{
  "preset": ["2015"]
}

Polyfill

Babel でトランスパイルすることで、古いブラウザでも動作する Javascript を出力できるようになったのですが、古いブラウザの標準オブジェクトの中には ES6 に対応していないものがあります。 そのために標準オブジェクトを拡張する Polyfill を導入します。

% npm install babel-polyfill --save-dev

わざわざ Polyfill が別ライブラリに分かれているのには、ちゃんと意味があります。 標準オブジェクトを拡張することは、既存の環境と互換性を失うことになります。 互換性を失うのは危険を伴うので、別ライブラリに分けているのです。 Polyfill を導入するときは、標準オブジェクトを拡張していることをちゃんと認識したうえで使う必要があります。

babel-runtime

上記のように Polyfill には標準オブジェクトを拡張するという問題があるので、それをしないようにする実装もあります。 それが babel-runtime です。 babel-runtime は標準オブジェクトの対応していない機能を、その場で別のコードにトランスパイルして解決します。

Polyfill を使うのか babel-runtime を使うのかは、決めの問題だと思うので、どちらかを導入すれば良いと思います。 Polyfill を導入しているケースが多いように思われますので、個人的には Polyfill でいいんじゃないかと思っています。

webpack

ブラウザで実行するには、複数に分けられたjsファイルを1つにして読み込まないといけません。 複数ファイルを読み込むことももちろんできますが、依存関係の解決とか大変ですよね。 そのためにビルドツールを使うわけですが、今回は webpack を採用しました。

webpack だと browserify と違って複数ファイルを生成するのが簡単にできるそうです。 (browserify使ったことないので、詳細はわかりません)

% npm install webpack babel-loader --save-dev

インストールすれば、すぐに webpack が使えます。 簡単ですね。 webpack は様々形式のデータを扱うのに、プラグイン形式で対応しており、babel を使う場合は babel-loader を使います。

これだけだと webpack がどのようにファイルをビルドするかがわからないので、設定ファイルを書きます。

webpack.config.js

webpack は設定ファイルを webpack.config.js で書くのですが、どうせなら設定ファイルも ES6 で書きたいですよね。 これをやるのはとても簡単で、bable-register をインストールすれば、 webpack.config.babel.js というファイルで設定を ES6 で書くことができます。

% npm install babel-register --save-dev

interpret

babel-register をインストールするだけで、なぜ ES6 で設定ファイルを書くことができるようになるのでしょうか。 そこには interpret というライブラリの存在があります。

interpret の仕組みはとても簡単で、設定された拡張子に対して動的な前処理を適用するだけです。 interpret の方で、 .babel.js という拡張子に対しては、 babel-register で変換して処理するという風に定義されていますので、 webpack.conf.babel.js でも問題なく処理できるというわけです。

つまり、interpret に対応しているツールに関しては、babel-register をインストールすれば、もれなく ES6 にも対応できるようになります。

JSのように逐次解釈して実行する言語をインタプリタ言語と言いますが、 interpret はインタプリタと同じ意味(品詞は違う)の単語で、とてもわかりやすい名前ですね。

webpack.config.babel.js

webpack.config.babel.js には次のような設定を書きました。

export default {
  entry: {
    main: './src/main.js',
    kintone: './src/kintone.js',
  },
  output: {
    filename: '[name].js',
    path: `${__dirname}/web`,
  },
  module: {
    loaders: [{
      test: /\.js$/,
      include: [
        `${__dirname}/src`,
        `${__dirname}/test`,
      ],
      loader: 'babel',
    }],
  },
};

entry には、どのファイルをビルドするのかを指定します。 ここでは、2つ(main, kintone)を指定しています。 このように、複数のファイルを指定できるのが、webpackの良いところですね。

output には、どのように出力するかを定義します。 ここでは web ディレクトリにビルド結果を出力するようにしています。

module.loader でローダの指定をします。 ここでは、 .js のファイルに対して、 babel-loader を使用して babel でトランスパイルするように指定しています。 include ではローダの対象となるファイルを指定しています。

相対パス地獄を解決する

相対パス地獄は ES6 だけでなく他の言語でも見られますが、みなさんも

require('../../../../foo.js');

のような相対パスでのモジュールの読み込みで苦い思いをした経験があるのではないでしょうか。 これは webpack の機能を使うことで解決できます。

webpack の設定の resolve.root でディレクトリを指定すれば、そのパスを起点としたモジュールが読み込めるようになります。 webpack.config.babel.js に記述を追加します。

  resolve: {
    root: [
      `${__dirname}/src`,
    ],
  },

この設定だと、例えば src/uuum/foo.js は、

import from 'uuum/foo';

のような記述で読み込みができるようになります。

ここで注意しないといけないのが、この機能は webpackが提供している機能 だというところです。 なので、 babel 単体ではうまく処理することができませんので、 webpack を通さない処理だと当然使用することができません。 例えば、 webpack.config.babel.js は、 webpack を通さずに直接 babel でトランスパイルするので、もし src/ 以下のファイルを読み込んでいた場合は、import に失敗します。(NODE_PATHを設定すれば大丈夫)

ソースマップ

Babel で ES6 で記述できるようになったのは良いのですが、ブラウザ上で実際に実行されるのは、トランスパイルされた Javascript なので、ブラウザ上でエラーが出た場合に元のソースコードのどこでエラーが発生したのかがわかりません。 それがわかるようにするためにソースマップを生成しておくと、オリジナルのソースコードのどこに対応するのかがわかるようになるので、デバッグが楽になります。

ソースマップを追加するのは devtoolinline-source-map を設定するだけです。

  devtool: 'inline-source-map',

名前の通り、この設定を追加すると生成されるファイルの中にソースマップが設定されます。 他にもソースマップの生成方法はいろいろありますが、詳しくはマニュアルをご参照ください。

ここでは1つ課題があって、本番環境ではソースマップは必要ないんですが、現状だと本番用でもソースマップが追加されてしまっています。 なので、本番環境と開発環境でわけないといけないのですが、 webpack.config.prod.babel.js の用に環境ごとに設定ファイルを分けるのが一般的なようですね。 これはおいおい解決していこうと思ってます。

Mocha

テストツールには Mocha を採用しました。 Mocha はシンプルな TDD/BDD 対応のテストツールです。 テストに必要な基本的な部分のみ実装していて、 assertion ですら外部のライブラリを使用します。 そのため時流に乗って適切なライブラリと組み合わせることができ、その点が気に入っています。

Mocha はインストールするだけで、すぐに使えるようになります。

% npm install mocha --save-dev

テストディレクトリは標準の test/ にします。

test/mocha.opts に Mocha のコマンドラインのオプションを書いておくと、自動的に適用されるようになります。 こうしておけば、 mocha コマンドを叩くだけでテストが実行できるようになります。

mocha.opts には次のような設定を書きました。

--compilers js:babel-register
--recursive
--require babel-polyfill
--require src/kintone

1行目の --compilers js:babel-register を指定しておくと、テストファイルを読み込む時に、 babel-register で前処理してくれるようになります。 つまり、テストコードも ES6 で記述できるようになります。

--recursive はその名の通り。

あとは Polyfill が必要なので読み込んでいるので、このプロジェクトは kintone ようなので、それ用のライブラリを読み込んでいます。

mocha コマンドは次のように実行します。

NODE_ENV=test NODE_PATH=$NODE_PATH:$PWD/src mocha

テストなので、 NODE_ENV に test をセットします。

NODE_PATH は先程の webpack のところでやった、相対パス地獄を回避するためにライブラリの読み込みパスを指定しないといけません。

power-assert

Mocha は assertion のライブラリを持っていないと書きましたが、 assertion には power-assert を採用しました。 power-assert を使うと、 assert で失敗した時の出力が超絶にわかりやすくなります。

どのような出力になるかは本家をご参照ください。(power-assert)

power-assert をインストールします。

% npm install power-assert babel-plugin-espower --save-dev

power-assert はそのままでは babel に対応していないので、 babel-plugin-espower も導入します。

.babelrc に次の設定を追加します。

  "env": {
    "test": {
      "plugins": [
        "espower",
      ]
    }
  }

power-assert はテスト環境だけで、動作すれば十分なので、テスト環境のみ espower を追加するようにしています。

Karma

ごめん、書くの疲れた。 また今度書きます。

感想

相変わらず JS 界はツール類が多くて大変というのが正直な感想です。 ブラウザの違い、バージョンの違い、サーバ・クライアントの違いと複雑な条件が絡み合っているので仕方がないとは思うのですが。。。

しかし、このあたりの仕組をちゃんと把握したうえで使いこなすのは、本当に大変だと思うし、今の環境も1年後には古くなっているのを考えると少し憂鬱な気持ちになってしまいます。

とはいえ、現環境ではまずまずの状態を作れたのではないかと思うので、しばらくはこの環境で開発を進めていこうと思っています。

まとめ

UUUMでは富士登山(任意参加!!)ができます。

f:id:masatobito:20160915160031j:plain

エンジニアで参加したのは僕だけでしたがw

wercker で Bitbucket のプライベートリポジトリをビルド!

新人エンジニアのハトネコエです。

UUUMでは毎週月曜日に社内勉強会をしていて、今週の担当は私なのですが、
昨日月曜日は台風のためお休みしましたので残念ながらおこなえず……

いえ、ごめんなさい!
実は土日かけて勉強会の準備してましたけどスライドはまだできてません!

土日は新幹線やホテルで、そして月曜は一日中、翌朝4時頃までがっつりやっていたのですが、
まだ発表できる段階まで至っていません。

これはテーマの決定をミスった気が……。

予定より軽めのテーマに変えることも考えつつ、
今日はその下準備の中で得たものを記事にしてみます。

個人開発はお金がない!

お金がないです。

でもソースは git で管理したい!

最近は GitHub の価格体系が変わり、
プライベートリポジトリをいくつ使用しても個人だと月800円程度、学生だと0円! と、とても安くなりました。
(以前はプライベートリポジトリの個数で月の料金が変わっていました)

とはいえ、Bitbucket のプライベートリポジトリは無料ですから、
個人開発やスタートアップ企業で使用しているところは多いことでしょう。

GitHub じゃないから Circle CI は使えないけど、カンタンなCIツールを使いたい!

そんなワガママを叶えてくれるのが、wercker です。

続きを読む

Railsの風が吹いたら確認したい、Rubyのモジュールシステム

こんにちは、入社して3ヶ月くらい経ちましたnakahashiです。

六本木のポケモンGOプレイヤーは気前がよく、職場周辺のポケストップはいつも花びらが舞っているので、キャッキャウフフな生活を過ごしています。

さて、UUUM攻殻機動隊では、最近Railsの風が吹き始めています。業務でRubyをどっぷり使い込んだことは個人的にはないので、言語の基本を見なおしているところです。

Rubyの基礎を勉強するにあたり非常に重要な、Rubyのモジュールシステムについてまとめてみました。

続きを読む

【小ネタ】Rails5でlogrageの出力にbacktraceを足す

nazoです。

Rails でログを出力する際に、書式とかをプラガブルに設定できる lograge という gem があるのですが、デフォルトで backtrace(スタックトレース) を含めてくれなくて困っていました。

従来はモンキーパッチで結構苦しい対応を迫られていたようですが、Rails5 から、payload に例外オブジェクトがそのまま入るようになった ので、

  config.lograge.custom_options = lambda do |event|
    { backtrace: event.payload[:exception_object].try(:backtrace) }
  end

で簡単に backtrace を挿入できるようになりました。便利ですね。