2015年4月14日火曜日

Rails をインストールする (Ubuntu/VirtualBox/Windows)

Windows 上に Rails をインストールしようとしたところ、簡単に解決しなさそうな問題がいろいろ出てきたので、Windows に直接 Rails をインストールすることは諦め※1、Windows に仮想化ソフト VirtualBox を入れてその上で Ubuntu を動かし、そこに Rails をインストールすることにした。しかしそれでも、幾つも問題に遭遇したので、手順を書き残しておく。

※1:その後、問題回避策として「gem update --system 2.3.0」をおこなったら、Windows でも Rails が動いた。(参考: Rubygems Issue 977


1. 仮想ハードディスクイメージのダウンロード

VirtualBox で作成する仮想マシンの仮想ハードドライブとして使用するイメージを「日本語 Remix 仮想ハードディスクイメージのダウンロード」ページからダウンロードする。現時点 (2015/4/14) では次の二つが存在するが、Ubuntu 14.04 LTS のほうは、VirtualBox で利用したときに黒画面のまま先に進まなくなるので、Ubuntu 12.04 LTS のほうを使う。


2. VirtualBox のインストール

Download VirtualBox」ページから Windows 用の VirtualBox をダウンロードし、インストールする。現時点 (2015/4/14) ではバージョン 4.3.26 が最新。

  • VirtualBox 4.3.26 for Windows hosts → x86/amd64

3. 仮想マシン作成

VirtualBox 起動後、「新規」ボタンを押して新しい仮想マシンの作成を開始する。「名前とオペレーティングシステム」のタイプとバージョンでは Linux と Ubuntu (32 bit) を選ぶ。(Ubuntu (64 bit) の選択肢は存在しない)


 「ハードドライブ」では、先にダウンロードしておいた Ubuntu の仮想ハードディスクイメージ (ubuntu-ja-12.04-desktop-i386.vhd) を指定する。



4. Ubuntu の初期設定

VirtualBox で、作成した仮想マシンを選択し、「実行」ボタンを押して仮想マシンを起動する。起動後、BIOS 云々のエラーメッセージが表示されるが、しばらくすると Ubuntu が起動する。案内に従って Ubuntu の初期設定をおこなう。


5. ディストリビューションのアップグレード

Ubuntu のデスクトップが表示されると、画面左側のメニューアイコン群内にあるアップデートマネージャーが、更新を知らせてくる。見ると、「Ubuntu の新しいリリース '14.04.2 LTS' が利用可能です」と言っている。そこで、促されるままにアップグレードをおこなう。なお、完了までにかなり時間がかかる。また、途中で幾つかアップデートに失敗するものがあり、確認ボタンを押すことを求められる(自動応答する方法があるとは思うのだが・・・)。




6. Ruby バージョンアップ

現時点 (2015/4/14) では、Ruby の最新バージョンは 2.2.2 である (2015/4/13 にリリース)。Ruby 2.2 系をインストールすることにするが、普通に apt-get install ruby をしても、Ruby 2.2 はインストールされない。そこで、BrightboxRuby packages for Ubuntu に書かれている手順を参考に Ruby 2.2 をインストールする。

apt-get install software-properties-common
apt-add-repository ppa:brightbox/ruby-ng
apt-get update
apt-get install ruby2.2


7. GEM アップデート

gem update --system


8. Bundler インストール

gem install bundler


9. Rails インストール

Rails のインストールは下記のコマンドで実行できるが、いろいろエラーが発生する。以降では、発生するエラーを一つずつ潰していく。

gem install rails


10. Ruby 開発用パッケージのインストール

最初のエラーは /usr/lib/ruby/include/ruby.h というヘッダーファイルが見つからないというエラー。

Fetching: nokogiri-1.6.6.2.gem (100%)
Building native extensions.  This could take a while...
ERROR:  Error installing rails:
        ERROR: Failed to build gem native extension.

    /usr/bin/rby2.2 -r ./siteconf20150414-3343-7itg1c.rb extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib/ruby/include/ruby.h

extconf failed, exit code 1

Gem files will remain installed in /var/lib/gems/2.2.0/gems/nokogiri-1.6.6.2 for inspection.
Results logged to /var/lib/gems/2.2.0/extensions/x86-linux/2.2.0/nokogiri-1.6.6.2/gem_make.out

Ruby エクステンションをコンパイルするためには Ruby 開発用のパッケージが必要だそうなので、インストールする。

apt-get install ruby2.2-dev
yum install ruby-devel


11. zlib インストール

ruby2.2-dev インストール後に再度 gem install rails を実行すると、次は zlib が見つからないというエラーが出る。

checking if the C compiler accepts ... yes
Building nokogiri using packaged libraries.
checking for gzdopen() in -lz... no
zlib is missing; necessary for building libxml2
??? extconf.rb failed ***

zlib は apt-get install zlib ではインストールできないので、「UbuntuでRals3.2.3 (4) はじめてのRubyGemsは・・・失敗。さあどうする?」を参考にして、下記のコマンドでインストールする。

apt-get install zlib1g-dev
yum install zlib zlib-devel patch

ここまでくれば、gem install rails は成功する。
gem install rails


12. SQLite3 インストール

Getting Started with Rails によると、SQLite3 が必要とのことなので、インストールする。なお、sqlite3-ruby gem は、名前が sqlite3 に変更されたとこのこと。

apt-get install sqlite3
apt-get install libsqlite3-dev
gem install sqlite3
yum install sqlite-devel


13. Rails アプリケーション作成

Rails アプリケーションを試しに作成してみる。

rails new sample


14. Rails アプリケーション実行

作成した Rails アプリケーションを実行してみる。しかし、エラーが出るので、一つずつ潰していく。

cd sample
bin/rails server


15. JavaScript ランタイムのインストール

Rails アプリケーション実行時に発生する最初のエラーは JavaScript ランタイムが見つからないというエラー。

/var/lib/gems/2.2.0/gems/execjs-2.5.2/lib/execjs/runtimes.rb:48:\
in `autodetect': Could not find a JavaScript runtime. See \
https://github.com/rails/execjs for a list of available runtimes. \
(ExecJS::RuntimeUnavailable)

Getting Started with Rails の 4.1 Starting up the Web Server の記述を頼りに Gemfile の中を覗くと、次のような行がある。

# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby

therubyracer というのが JavaScript ランタイムの一つらしいので、これをインストールしてみる。

gem install therubyracer

しかし、ここでエラーが発生する。(次へ)


16. コンパイラーインストール

therubyracer インストール時に発生するエラーは、コンパイラーが無いというエラー。

/var/lib/gems/2.2.0/gems/libv8-3.16.14.7/ext/libv8/builder.rb:50:\
in `block in build_libv8!': No compilers available \
(RuntimeError)

このエラーメッセージを頼りにネットを検索すると、「Rails 4 で libv8, therubyracer のインストールにエラー発生」に問題解決方法の記述を発見。update-alternatives のコマンドラインだけ少し変更して実行。

add-apt-repository ppa:ubuntu-toolchain-r/test
apt-get install gcc-4.9
apt-get install g++-4.9
update-alternatives \
  --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 100 \
  --slave   /usr/bin/g++ g++ /usr/bin/g++-4.9
yum install gcc-c++

ここまでくれば、libv8 と therubyracer のインストールは成功する。

gem install libv8
gem install therubyracer


17. JavaScript ランタイム使用

Gemfile の「# gem 'therubyracer', platforms: :ruby」と書かれている行をコメントインし、bundle install する。


vi Gemfile
bundle install


18. Rails アプリケーション実行 (再掲)

やっと Rails アプリケーションを実行できる。

bin/rails server

うまく Rails アプリケーションが起動した場合は、ポート番号 3000 番でHTTP サーバーが待ち受ける。





以上

2015年4月7日火曜日

Function to define a namespace in JavaScript (namespace.js)

Sample Code:

// Define a namespace 'aaa.bbb.ccc' and add a function 'hello'
// under the namespace which prints 'Hello, world.'.
namespace('aaa.bbb.ccc').hello = function() {
    print('Hello, world.');
};

// Execute the function.
aaa.bbb.ccc.hello(); 


Source Code:

2015年3月21日土曜日

iBeacon as a kind of AD structures

First of all, iBeacon should be parsed as a kind of AD structures. Any library that is not implemented that way is just "usable" at best.

The AD structure format is described in "11 ADVERTISING AND SCAN RESPONSE DATA FORMAT" of "Bluetooth Core Specification 4.2". You can find the document at Specification Adopted Documents.

nv-bluetooth is a utility library written in Java and it contains ADPayloadParser class that parses a payload of an advertising packet (byte[]) and returns a list of AD structures (List<ADStructure>). With the library, an implementation of onLeScan method (of android.bluetooth.BluetoothAdapter.LeScanCallback interface) can be written like the following.


public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
    // Parse the payload of the advertising packet.
    List<ADStructure> structures =
        ADPayloadParser.getInstance().parse(scanRecord);

    // For each AD structure contained in the advertising packet.
    for (ADStructure structure : structures)
    {
        if (structure instanceof IBeacon)
        {
            // An iBeacon packet was found.
            handleIBeacon((IBeacon)structure);
        }
        ........


ADPayloadParser class holds implementations of ADStructureBuilder interface and ADManufacturerSpecificBuilder interface. ADStructureBuilder interface has a method to build an instance of ADStructure from a byte array, and ADManufacturerSpecificBuilder interface has a method to build an instance of ADManufacturerSpecific from a byte array. As you guess, you can parse AD structures in special formats by registering implementations of these interfaces into ADPayloadParser.

nv-bluetooth supports some other AD structures in addition to iBeacon. Especially, ucode (ITU-T H.642) is supported. See README.md and JavaDoc of nv-bluetooth for details.




まず初めに、iBeaconAD structure の一種としてパースすべきです。そのように実装されていないライブラリは、せいぜい「使える」程度に過ぎません。

AD structure のフォーマットは Bluetooth Core Specification 4.211 ADVERTISING AND SCAN RESPONSE DATA FORMAT に記載されています。この文書は Specification Adopted Documents にリストされています。

nv-bluetooth は Java で書かれたユーティリティーライブラリで、アドバータイジングパケットのペイロード (byte[]) をパースして AD structure のリスト (List<ADStructure>) を返す ADPayloadParser というクラスを含んでいます。このライブラリを使うと、(android.bluetooth.BluetoothAdapter.LeScanCallback インターフェースの) onLeScan メソッドの実装は次のように書くことができます。


public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
    // アドバータイジングパケットのペイロードをパースする。
    List<ADStructure> structures =
        ADPayloadParser.getInstance().parse(scanRecord);

    // アドバータイジングパケットに含まれる各 AD structure ごとに
    for (ADStructure structure : structures)
    {
        if (structure instanceof IBeacon)
        {
            // iBeacon パケット発見。
            handleIBeacon((IBeacon)structure);
        }
        ........


ADPayloadParser クラスは ADStructureBuilder インターフェースと ADManufacturerSpecificBuilder インターフェースの実装を保持しています。ADStructureBuilder インターフェースは、バイト配列から ADStructure のインスタンスを生成するためのメソッドを持ち、ADManufacturerSpecificBuilder インターフェースは、バイト配列から ADManufacturerSpecific のインスタンスを生成するためのメソッドを持っています。ご想像のとおり、これらのインターフェースの実装を ADPayloadParser に登録することにより、特殊なフォーマットの AD structure をパースすることができます。

nv-bluetooth は iBeacon 以外にも幾つか AD structure をサポートしています。特に、ucode (ITU-T H.642) をサポートしています。詳細は nv-bluetooth の README.mdJavaDoc を参照してください。

2015年2月20日金曜日

Redshift の文字列型はバイト単位!?


私の勘違いでなければ、

通常の PostgreSQL の場合、character varying(N) などの N は「文字数単位」ですが、PostgreSQL 8.0.2 から派生した Amazon Redshift の場合は「バイト単位」になるようです。

PostgreSQL ドキュメント 「Character Types」 より抜粋

SQL defines two primary character types: character varying(n) and character(n), where n is a positive integer. Both of these types can store strings up to n characters (not bytes) in length.

Redshift ドキュメント 「Character Types」 より抜粋

CHAR and VARCHAR data types are defined in terms of bytes, not characters.

ですので、UTF-8 で文字データを格納するとした場合、UTF-8 では一文字のバイト数が最大 4 バイトになることを考慮して、「最大文字数 × 4」でカラムを定義しないといけないでしょうね。例えば、最大 100 文字を格納したいのであれば、character varying(400) というカラム定義になります。Unicode や UTF-8 については、「Unicode 理解度簡易チェック」や「文字数、UTF-8 でのバイト数、サロゲートペアの数を数える」も参照してください。

Redshift には、その他にも驚くような PostgreSQL との差異があるので、例えば Primary Key や Unique 制約が無視されたり Index を作れなかったりするので、「Redshift を単なる PostgreSQL の派生物」だと思ってスキーマ設計していると、はまりますね。

2014年12月16日火曜日

Sinatra + SSL

Found a better way to enable SSL in Sinatra than "Sinatra+Thin+SSL". This is a generic way and does not require Thin.

2014年10月1日水曜日

Sinatra + Thin + SSL

Finally found a way to enable SSL in Sinatra + Thin.

# [2014/12/16]
# Found a better way.
# See "Sinatra + SSL".


Start this script (sinatra+thin+ssl.rb) then type:
curl -k https://localhost/
and you will see "Hello, SSL."

2014年9月20日土曜日

MissingTableException on Google Cloud SQL

If you are using JDO to access Google Cloud SQL and suffering from MissingTableException like below:

org.datanucleus.store.rdbms.exceptions.MissingTableException: Required table missing : "`TABLE NAME`" in Catalog "" Schema "". DataNucleus requires this table to perform its persistence operations. Either your MetaData is incorrect, or you need to enable "datanucleus.autoCreateTables"

and if your table names contain lowercase letters, probably the issue can be solved by setting "datanucleus.identifier.case" properly.

"JDO : Datastore Identifiers" says "By default, DataNucleus will capitalise names". Therefore, if your table names contain lowercase letters, "datanucleus.identifier.case" should be set explicitly.

The valid values for "datanucleus.identifier.case" are UpperCase, LowerCase or PreserveCase (or MixedCase; See Change "datanucleus.identifier.case" 'PreserveCase' to be 'MixedCase' to be match internal namings). So, for example, your jdoconfig.xml will have to have the entry like the following.

<property name="datanucleus.identifier.case" value="LowerCase"/>

If you are developing your GAE application on Windows or Mac OS X, you may not encounter this case sensitivity problem until you deploy your application onto GAE. See "9.2.2 Identifier Case Sensitivity" (MySQL Reference Manual) for details.