PadrinoでHamlを使っているが以下のようなエラーが発生する。

Encoding::UndefinedConversionError – “\xE4″ from ASCII-8BIT to UTF-8”

対処方法としては-# Encoding:utf-8をファイルの最初の行に追加する。
Ruby1.9になって明示的に文字コードを指定しないとASCII-8BITと認識するみたいだ。

Ubuntu 8.04上でWordPress3を動かして、管理画面で作成した固定ページのパーマリンクを変えた時、404 Not Foundエラーが出てしまうので半日はまった。
最初、WordPressの設定が悪いのかと思って色々設定を変えたが変わらず。
ネットで調べていると以下のページでApacheのrewriteモジュールが有効になっていないことに気づく。

WordPressでパーマリンク設定後に404エラーが出る場合

以下のコマンドでRewriteモジュールを有効化する。
sudo a2enmod rewrite

Apacheのサイト設定ファイルのディレクトリ設定のAllowOverrideをAllに設定する
/etc/apache2/sites-enable/000-xxxx

Options FollowSymLinks MultiViews
AllowOverride All < -- 変更 Order allow,deny allow from all

Apacheを再起動する。
sudo /etc/init.d/apache2 restart

これで変更したパーマリンクをブラウザで指定すると該当ページが表示されるようになる。

Rails3のアプリケーションをクラウドサービスのHerokuを使ってみた。
登録方法はこちらを参照した。

HerokuでRuby1.9とRails3を使う

git push heroku masterコマンド発行時、fatal errorが発生。
以下のコマンドでgitリポジトリの設定を行う。

git remote add heroku git@heroku.com:プロジェクト名.git

これでgit push heroku masterコマンドが成功。
http://プロジェクト名.heroku.comでちゃんとRailsが動作していることが確認できた。

VirtualBox 3.2.6は、シームレスモードやカーソルがキャプチャーされないなど使い勝手がかなりよくなった。
しかし、Ubuntu 10.04をゲストOSで使う場合はアドオンモジュールを入れないと画面解像度が800×600に固定されて変更ができない。

Ubuntuで画面解像度を変更できるようにするには以下の手順で行う。

1 VirtualBox上でUbuntuを立ち上げる

2 Virtualboxメニューのデバイス- CD/DVDデバイスでVBoxGuestAddisions.isoを選択する。

3  UbuntuのターミナルでCDROMデバイスをマウントする
# mount /dev/cdrom /mnt

4 /mnt下のautorun.shをルート権限で実行する。

6 別ウィンドウにビルドの経過が表示される。終了したらリターンキーをたたく。

5 インストール終了後再起動する。

6  VirtualBoxメニュー 仮想マシン-フルスクリーンモードにする でフルスクリーンになるか確認する。

Ubuntu Server 8.04(Hardy)にBazaarをインストールする場合、普通にapt-getをすると古いバージョンがインストールされてしまうので、開発サイトから直接インストールできるようにする。

/etc/apt/sources.listに以下の2行を追加する。

deb http://ppa.launchpad.net/bzr-beta-ppa/ppa/ubuntu hardy main
deb-src http://ppa.launchpad.net/bzr-beta-ppa/ppa/ubuntu hardy main

以下のコマンドをシェルで実行して公開鍵の登録を行う

# sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 37B19B80

以下のコマンドをシェルで実行する

# sudo apt-get update
# sudo apt-get bzr

参考URL
https://launchpad.net/~bzr-beta-ppa/+archive/ppa

iPhoneのTableViewでセル削除を行わせたいとき、以下のような画面を表示して行う。

holidaystableview

これを行うためにテーブルビューコントローラーはUITableViewDelegateプロトコルとUITableViewDataSourceプロトコルを実装してcommitEditingStyleメソッドを実装する必要がある。

@interface HogeTableViewController : UITableViewController &amp;gtUITableViewDelegate ,UITableViewDataSource&lt; {
    NSMutableArray *array
}
@end

@implementation HogeTableViewController
...
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]  withRowAnimation:UITableViewRowAnimationFade];
    // Delete the row from the data source
    NSInteger row = [indexPath row];
    [self.array removeObjectAtIndex: row];
    }
}
@end

(EditModeに変更するコードは省略)

テーブルビュー上でセルを削除すると上のcommitEditingStyleが呼ばれる。
しかし、上のコードではdeleteRowsAtIndexPathsメソッドを呼んだ時点でエラーになってしまう。
どうやらテーブルビューはデータソースの状態をモニターしているらしく、上のコードで言うとarray変数の要素数とテーブルビューのセル数が違っているとエラーではねる仕様になっているらしい。
データソースはおそらくヘッダーファイルで一番最初に宣言されている配列をデータソースとしているのではないかと思われる。
従って、以下のようにデータソースの要素を削除してからテーブルビューのセルを削除すると正常に終了する。

少し気持ち悪い仕様だが、iPhoneでソフトウェアを作るかぎりでは仕方ないのだろう。

iPhoneのアプリでよくあるインターフェースがリストを表示してアイテムを選択すると詳細ページを表示するというパターンだ。

table

上のリストの一つをタップすると詳細ページが表示される。
これだけだったら以下のコードをtableViewControllerに追加すれば実現できる。

tableViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
	// テープルコントローラーで何番目のセルが選択されたか
	NSInteger row = [indexPath row];
       // nibファイルを読み込んで詳細ページのコントローラーを生成
	if (detailViewController == nil){
		LocationMemoDetailViewController *memoDetail = [[LocationMemoDetailViewController alloc] initWithNibName:@"MemoListDetailView" bundle:nil];
		detailViewController = memoDetail;
		[memoDetail release];
	}
       // 詳細ページへ切り替え
	[navController pushViewController:detailViewController	animated:YES];
}

上のコードはtableViewControllerのリストアイテムがタップされたときに呼ばれるdidSelectRowAtIndexPathメソッドである。
コードのdetailViewControllerが詳細ページのコントローラークラスである。
これで詳細ページに何か情報を渡したいい場合は以下のようなコードを追加すればよさそうに思われるだろう。

tableViewController.m

detailViewController.nameField.text = @"山田 太郎";

ここでnameFieldは詳細ページ上にあるUITextFieldのオブジェクトである。
しかし、これで詳細ページを表示しても設定された値は表示されない。
どうやら詳細ページの中身が生成されるのは表示されるときのようなのでnibファイルを読み込んだだけではアクセスできないようである。
この場合、detailViewControllerクラスにテキストフィールドに表示するデータを一時保管しておく変数を追加する。

detailViewController.h

@interface LocationMemoDetailViewController : UIViewController {
...
NSString *name;
}
@propety(nonatomic,retain) NSString* name
</pre>

detailViewController.m
<pre name="code" class="java">
...
@synthesize name

そしてtableViewController側にはviewWillAppearメソッドを以下のように追加する。

- (void)viewWillAppear: (BOOL) animated {
	self.nameField.text = self.name;
}

つまり、詳細ページが表示されたときに一時保管してある文字列をテキストフィールドに設定するのである。

このあたりはiPhoneのUIの中身が隠蔽されているのでわかりにくい部分だ。
APIを呼ぶだけで結構な仕事をしてくれるので楽なのだが、その引き換えに中の動きがわかりずらくとまどうことが多い。
このあたりもiPhoneで開発する上でのノウハウなのだろう。

iPhone SDK 3でターゲットを「Simulator – 3.0|Debug」にしてビルドすると(プロジェクト名)_Prefix.pchファイルで以下のようなエラーが出ることがある。

error: syntax error before ‘AT_NAME’ token
error: syntax error before ‘}’ token
fatal error: method definition not in @implementation context

原因はコンパイラーのバージョンによってiPhone OS 3.0用実行ファイルのコンパイルができないようである。
回避方法は以下の通り。

1  XCodeのメニュー「プロジェクト」-「プロジェクト設定を編集」を選択する。
2  一番上のタブの「ビルド」を選択する。
3  「コンパイラのバージョン」項目を選択する。
4  「C/C++コンパイラのバージョン」の値を「GCC 4.0」にする。
5  「C/C++コンパイラのバージョン」が選択されている状態でウィンドウの左下隅にある歯車アイコンをクリックし、「ビルド設定条件を追加」メニューを選択する。
6  新しいエントリーが追加されるので一番左の項目をクリックし、「Device – iPhone 3.0」を選択する。そして一番右の項目をクリックし「GCC 4.2」を選択する。
7  もう一度5,6の作業をくりかえし、左の項目「Simulator – iPhone3.0」を選択し右の項目「GCC 4.2」を選択する。

今やリレーショナルデータベース全盛の時代である。

どんなシステムもRDBなしには成り立たなくなっている。

しかし、RDBは本当に便利なのだろうか?

例えば、いまはやりのSNSを考えてみよう。

それぞれのユーザーは他のユーザーとネットワーク的につながりをもっている。

そして、そのつながりは友人関係だったり仕事仲間だったりする。

RDBではそれぞれの表の属性もあらかじめ定義される必要があり、後で属性を追加することは難しい。

しかし、SNSのような人間関係を表現するようなもので事前にデータ構造を予測することができるだろうか。

例えば最初は仕事で知り合った人間でも友人になることがあるし、恋人同士だったのが別れてしまって他人同士になってしまうこともあるだろう。

このようなダイナミックなデータ構造はRDBでは表現するのが難しいだろう。

しかし、グラフDBはこのような用途に向いたDBである。

例えば、Todoリストのデータを考えてみよう。

neo4j-011

上図の四角がノードとよばれるものでRDBでいう1レコードのデータを表す。

上の例ではタスク1ノードはタスク名、担当者名、タスク内容、期間という属性をもっていてそれぞれ値をもっている。

また、ノード間はリンクと呼ばれるもので接続される。

リンクは2ノード間の関係を表すものでどういう関係かをリンクの属性によって知ることができる。

ここではNEXTという属性によってタスクの順番を表現している。

このようにグラフDBはRDBとは根本的に違うデータ構造をもっている。

従って問い合わせもSQLではなくグラフをスキャンするAPIでデータを取り出す。

Neo4jはJavaで書かれたグラフDBライブラリである。

Neo4jを使ったプログラム例はこのようになる。

import org.neo4j.api.core.*;

public enum NeoTodoRelationTypes implements RelationshipType {
    NEXT
}
NeoService db = new EmbeddedNeo("var/base");
Node node1 = db.createNode();
node1.setProperty("name", "task1");
node1.setProperty("user", "鈴木");
node1.setProperty("content", "お仕事やってます");
node1.setProperty("due_date", "2009/6/30");
node2.setProperty("name", "task2");
node2.setProperty("user", "田中");
node2.setProperty("content", "あとは引き受けた!");
node2.setProperty("due_date", "2009/7/6");
 Relationship relation = node1.createRelationshipTo(node2,NeoTodoRelationTypes.NEXT);

import文でNeo4jライブラリをインポートしておく。

RelationshipTypeはリンクの属性を表すenumで「次へ」を表すNEXTを属性として持たせる。

EmbeddedNeoはNeo4j DBの初期化を行う。

次のcreateNodeでノードを一つ作成する。

そしてsetPropertyでノードに属性とデータを設定する。

次にノードを二つ作成しcreateRelationshipToでnode1とnode2のリンクを設定する。

これでリンクでつながった2つのノードの作成が完了する。

この要領でノード同士をつないでいけばノードのネットワークが出来上がる。

では、このネットワークからどのようにデータを取り出せばいいのだろうか

Transaction tx = db.beginTx();
try {
    Traverser tr = node1.traverse(Traverser.Order.BREADTH_FIRST,
                           StopEvaluator.END_OF_GRAPH,
                           ReturnableEvaluator.ALL,
                           NeoTodoRelationTypes.NEXT,
                           Direction.BOTH);
    Collection&lt;node&gt; node_list = tr.getAllNodes();
} finally {
    tx.finish();
}

Nodeクラスのtraverse APIでグラフネットワークをスキャンすることができる。

まず最初のノードのtraverseメソッドを呼ぶ。

1つ目の引数はスキャンする順番を指定するもので、BREADTH_FIRSTの意味は同じレベルにあるノードを最初にスキャンしてからより深いレベルのノードをスキャンするという意味である。

2つ目の引数はスキャンを停止する条件を指定する。

END_OF_GRAPHはグラフの最後まで来たら終了するという意味である。

3つ目の引数はどのノードの情報を返すかを指定する。

ALLなので全て返す設定になる。

4つ目はスキャンするリレーションタイプを指定する。

NEXTのリレーションタイプでつながっているノードをスキャンする。

最後はスキャンする方向を指定する

ノードからみてスキャンが他から入ってくる方向の場合はINCOMING、出て行く方向の場合はOUTGOINGとなる。

BOTHは両方の方向でのスキャンを指定する。

traverse実行後getAllNodesを呼ぶとスキャンされたノード情報がCollectionとして取得することができる。

後はイテレータで各ノードの情報をとればよい。

事前にデータ構造を決定することができてデータの整合性が重要なシステムにはRDBを使うべきだろう。

しかし、データ構造がダイナミックに変化するシステムではグラフDBを使った方が効率よく開発することができる。

これからは用途に合わせてデータベースも選ぶ時代になりつつあるのではないだろうか。

今、話題のクラウドサービスで一番有名なAmazon EC2を使ってみた。
まずはアカウントを登録する必要がある。

登録方法に関しては以下のページを参考にした。

「Amazon EC2」と「Amazon S3」を実際に使ってみたので、まずはアカウント作成まで」

「Amazon EC2」と「Amazon S3」を実際に使ってみた、今度はEC2の操作環境セットアップ

登録も済んでAccess KeyとSecret Access Keyを取得できたらEC2管理用FirefoxプラグインElastics Foxをこちらからダウンロードする。
ElasticFoxプラグインをインストールしてメニューの「ツール」-「Elasticfox」を選択すると下の画面が表示される。

elasticfox11.gif

ツールバーの下にある「Credentials」ボタンを押すと下図のようにダイアログボックスが表示される。

elasticfox2.gif

「Account Name」に登録したアカウント名、「AWS Access Key」と「AWS Secret Access Key」に取得したアクセスキーとシークレットアクセスキーを入力する。
「Add」ボタンを押してダイアログを閉じる。

「Machine Images (AMIs) 」タイトル下の一番左のRefleshボタンを押すとOSイメージの一覧が表示される。

elasticfox3.gif

次にsshでアクセスするための秘密鍵の生成を行う。
Elasticfoxの画面の「KeyPairs」タグをクリックすると秘密鍵を作成する画面が表示される。
タブ下の緑の鍵印ボタンを押すとKeypair名を入力するダイアログが出る。

elasticfox4.gif

Keypair名を入力してOKボタンを押すと秘密鍵ダウンロードのダイアログが表示される。
elasticfox5.gif

保存ボタンを押すとPCに秘密鍵ファイルがダウンロードされる。
作成したKeypairがリストに表示される。
elasticfox6.gif

次にセキュリティルールを設定する。
「Security Groups」タブをクリックする。

elasticfox9.gif

「Group  Permission」にあるGrantPermissionボタン(緑のチェック)をクリックするとプロトコルごとのセキュリティルールを設定するダイアログが表示される。

elasticfox10.gif

sshアクセスを許可するネットワークアドレスもしくはホストアドレスを設定する。
またhttpはどこからでもアクセスできるように設定する。

次にOSを起動する。「AMI and Intances」タブをクリックして好きなOSイメージを選択する。
タブ下の緑の起動ボタン(丸に縦棒のアイコン)をクリックすると以下のダイアログが表示される。
elasticfox7.gif

「Keypair」コンボボックスで先ほど作成したKeypaire(sample_key)を選択して右下の「Launch」ボタンを押す。
下のリスト「Your Instances」リストに起動したOS インスタンスが表示される。
2〜3分するとStateがpendingからrunningに変わる。
その後、sshで起動したOSにアクセスする。
「Your Instances」のOSイメージエントリーを右クリックして「Copy Public DNS to Clipboard」を選ぶとサーバーDNS名がコピーされる。

MacまたはLinuxからアクセスする場合はダウンロードした秘密鍵を sshコマンドで以下のように指定する。

# ssh -i 秘密鍵ファイルへのパス root@サーバーDNS名

ログインしたら通常のLinuxの操作を行うことができる。

login1.gif