2009年10月31日 (土)

windowsでgemで入れたコマンドがすべてin `load': no such file to load になる

WindowsのRuby実行環境としてActiveScriptRuby 1.8.7(p174) with-winsock2 
をインストール。
環境変数PATHにC:/Program Files/ruby-1.8/binを追加し再起動
(環境変数の設定を反映させるため。)

C:\>gem --version
1.3.4

C:\>gem install rake
Successfully installed rake-0.8.7
1 gem installed
Installing ri documentation for rake-0.8.7...
Installing RDoc documentation for rake-0.8.7...

C:\>rake --version
C:/Program Files/ruby-1.8/bin/rake:18:in `load': no such file to load --
C:/Program Files/ruby-1.8/lib/ruby/gems/1.8/gems/rake-0.8.7/bin/rake"
(LoadError)
        from C:/Program Files/ruby-1.8/bin/rake:18

疑問:
え!? rake 入れたばっかりなのに、なんでno such file?
答え:
実はgemのversion 1.3.4には実行ファイルへのパスにスペースが含めないバグ
があるせいで、実行できない。

疑問:
ruby consoleだと、rakeがちゃんと動作する。なんで!?
答え:
ruby consoleはコマンドプロンプト立ち上げ時に環境変数PATHの先頭に
C:\PROGRA~1\ruby-1.8\bin;を追加している。PROGRA~1という
ディレクトリ名にはスペースが含まれないため、gemのバグを回避している。

疑問:
C:\PROGRA~1って何?
答え:
8.3形式の短いファイル名を表示させる に記述されている通り、Windowsは、
昔のDOSに対応できるよう、ディレクトリやファイル名に自動的に8.3形式の
別名を割り振り、どちらの名前を指定しても同じ動作になる。

疑問:
で、rakeを実行するにはどうすればいいの?
答え:
・環境変数PATHにC:/Program Files/ruby-1.8/binではなく、
C:\PROGRA~1\ruby-1.8\binを追加する。(消極的解決法

・gemをversion1.3.5にアップデートする。(積極的解決法

疑問:
gemってどうやってアップデートするの?
答え:

C:\>gem install rubygems-update
Bulk updating Gem source index for:
http://gems.rubyforge.org/
Succeccfully installed rubygems-update-1.3.5
1 gem installed

C:\>set PATH=C:\PROGRA~1\ruby-1.8\bin;%PATH%

C:\>update_rubygems

新しいコマンドプロンプトを立ち上げ、rakeが実行できるか確認する。


C:\>rake --version
rake, version 0.8.7


CONGRATULATION!!

| | コメント (2) | トラックバック (0)

2009年10月25日 (日)

Amazon S3にバックアップをする

会社でサーバのファイル郡をAmazon S3にバックアップすることになり、その
ためのツールをRubyで作成しました。
会社の了解を得て、オープンソースにしていいことになったので、rubyforgeに
登録しました。
S3Backup:http://rubyforge.org/projects/s3backup/

S3Backupについて

概要
S3Backupツールとは、指定したディレクトリ以下をAmazon S3にバックアップ
/リストアするためのツールです。

特徴としては下記があります。

圧縮
Amazon S3にアップロードする際に各ディレクトリを圧縮するため、通信帯域や保存領域を節約することができます。

暗号化
設定によりアップロードするファイルを暗号化させることもできます。

差分バックアップ
バックアップが前回バックアップした時と内容が変わらないディレクトリは、
アップロードしないため、通信帯域や時間を節約することができます。

レジューム
通信エラー等で途中でバックアップが中断されても、次回実行時に前回
送信に成功したディレクトリは再送信されません。

※注
ディレクトリの内容が変わったかどうかの判断は下記によります。
・ファイルの追加
・ファイルの削除
・ファイルの更新日付の変更
・ファイルのサイズの変更
・シンボリックファイルのリンク先の変更

インストール
sudo gem install s3backup

設定ファイル
S3Backupツールのバックアップ・リストアの実行には下記の内容がyamlフォーマットで書かれた設定ファイルを予め準備しておく必要があります。

bucket: "バケット名"
directories:
- "バックアップもしくはリストア対象のディレクトリへの絶対パス"
- "ディレクトリへの絶対パス(複数ある場合は以降続ける)"
access_key_id: 'Amazon access_key_id'
secret_access_key: 'Amazon secret_access_key'
password: 'ファイルを暗号化する際のパスワード(任意)'
salt: '16文字のHex文字列(8Byte)passwordが指定されている場合のみ必要'
BUF_SIZE:バッファーサイズのbyte数(任意)
proxy_host:プロキシサーバのアドレス(任意)
proxy_port:プロキシサーバのポート(任意)
proxy_user:プロキシサーバのログイン名(任意)
proxy_password:プロキシサーバのパスワード(任意)

設定の説明
bucket

任意のファイルを登録できるコンテナ。指定されたbucketがなかった場合は作成される。Amazon S3内で一意である必要。

directories
バックアップもしくはリストアしたいディレクトリ。複数指定できる。またリストアの場合はバックアップされているディレクトリの配下なら任意のディレクトリを指定できる。リストア時にdirectoriesを指定しない場合は、指定したbucketにバックアップされたすべてのディレクトリがリストアされる。

access_key_id
Amazonより渡されたユーザーごとのid

secret_access_key
Amazonより渡されたユーザーに対する秘密のパスワード

password

AES-CBC-256形式でファイルを暗号化する際のパスワード。なお、設定されていない場合は暗号化しない

salt
AES-CBC-256形式でファイルを暗号化する際のSalt。16文字のHex文字列(8Byte)。passwordが指定されている場合のみ必要'

BUF_SIZE
デフォルト128M ディレクトリを圧縮した後、BUF_SIZEに分割し、送信する。最大5G。

proxy_host
プロキシサーバのアドレス(プロキシサーバ使用時のみ)。

proxy_port
プロキシサーバのポート(プロキシサーバ使用時のみ)。

proxy_user
プロキシサーバへのログイン名(プロキシサーバ使用時かつログイン必須の場合のみ)。

proxy_password
プロキシサーバへのログインのパスワード(プロキシサーバ使用時かつログイン必須の場合のみ)。

コマンドシンタックス

バックアップの場合
s3backup
[-f 設定ファイル] [-v デバッグメッセージの出力] [-l ログのパス] [-h ヘルプメッセージ]

  • 設定ファイル 設定しない場合はカレントディレクトリのbackup.ymlを読み込む。
  • デバックメッセージ バックアップ対象のディレクトリのファイルツリー構成と更新があったファイル名を出力
  • ログのパス 設定しない場合は標準出力に出力されます
  • ヘルプ ヘルプメッセージが出力されます

リストアの場合
s3backup -r [-f 設定ファイル] [-v デバッグメッセージの出力] [-l ログのパス] [-o 出力ディレクトリ] [-h ヘルプメッセージ]

  • 設定ファイル 設定しない場合はカレントディレクトリのbackup.ymlを読み込む。
  • デバックメッセージ バックアップ対象のディレクトリのファイルツリー構成と更新があったファイル名を出力
  • ログのパス 設定しない場合は標準出力に出力されます
  • 出力ディレクトリ リストア先のディレクトリを指定します。 設定しない場合はカレントディレクトリに出力されます。
  • ヘルプ ヘルプメッセージが出力されます

| | コメント (0) | トラックバック (0)

2009年10月10日 (土)

WindowsでgvimでTwitter

香り屋 さんでdownloadできるwindowsのgvim上でTwitterを行うための手順。
仕事中も作業をしながら、ちょこっとTLが見れる。

  1. もし、cURLがない場合は、香り屋さんでcurl.exeをdownloadし、gvim.exeと同じディレクトリに置く。
  2. もし、rubyがインストールされていない場合は、ActiveScriptRuby からdownloadし、インストール
  3. TwitVim をdownloadし、downloadしたファイルをgvim上で開いた状態で、 :source %を実行することでインストール。
  4. $HOME\_gvimrcに下記を追記。
    let twitvim_login
    = "ユーザー名:パスワード"
    let twitvim_count
    = 1から200までのTL数
  5. Windowsの場合は、文字化けするため、$VIMRUNTIME\plugin\twitvim.vimを下記のように修正

1336c1336,1361
<     let s = substitute(s, '&#\(\d\+\);','\=nr2char(submatch(1))', 'g')
---
>     let s = substitute(s, "'","''", 'g')
>     ruby << EOF
> str = VIM.evaluate("s")
> def ucs2_to_utf8(c)
>   raise if c < 0
>   return sprintf("%c", c) if c <= 0x7F
>   if c <= 0x07FF
>       c1 = 0b1100_0000 | (c >> 6)
>       c2 = 0b1000_0000 | (c & 0b111111)
>       return sprintf("%c%c", c1, c2)
>   end
>   if c <= 0xFFFF
>       c1 = 0b1110_0000 | (c >> 12)
>       c2 = 0b1000_0000 | ((c >> 6) & 0b111111)
>       c3 = 0b1000_0000 | (c & 0b111111)
>       return sprintf("%c%c%c", c1, c2, c3)
>   end
>   raise
> end
> require 'nkf'
> out = str.gsub(/&#\d+;/) do |m|
>   ucs2_int = m[2 .. -2].to_i
>   NKF.nkf("-W -s",ucs2_to_utf8(ucs2_int))
> end
> VIM.command("let s='%s'" % out)
> EOF

以上

gvim上で:FriendsTwitterを実行することにより、TLが表示される。
詳細は:help twitvim.txt を実行すること。

注意
let twitvim_enable_ruby = 1にしないこと
本来はRubyをインストールしている状態でlet twitvim_enable_ruby = 1に
すれば、cURL(外部コマンド)の代わりにRubyで処理されるため、TLの表示が
高速になるのだが、:help twitvim.txtにもあるとおり、Windowsのvimでの
Rubyの実行はバグのため、ソケットまわりの処理がすべてエラーになる。
http://www.mail-archive.com/vim_dev@googlegroups.com/msg03713.html
なので、Twitterから受信したUCS-2のコードをWindows用にSJISに変換する
ためのみに、Rubyを使用している。

謝意
ucs2_to_utf8の関数は下記のサイトに掲載されていたものをそのまま使用
しました。感謝しています。
http://d.hatena.ne.jp/elm200/20080709/1215558613

| | コメント (0) | トラックバック (0)

2009年8月 7日 (金)

Railsで掲示板を作成

Railsの案件を受注する条件として一晩でRailsで掲示板を作ってくれと言われた。
夜の7時ぐらいに連絡があり、朝の9時10時には、仕上げてほしいと、かなりの無茶振り。
でも、せっかくなので、作ってみた。
Commentboard

12時まで、デザインで悩む。
いろいろなサイトを参考にして、上記のデザインに決定。
Rspecのテストファーストで開発をする。はっきりいって、使い捨てのシステムにテストファースト開発する意味など無かった。
ただ、癖にしとかないと、ついつい言い訳をしてテストファーストをしない体質になるのが怖かったので、時間が掛かるのを承知でテストファーストにした。

案の定、Rspec_on_railsのpostメソッドの使い方が解からず2時間ほどはまった。
モデルのフィールド、たとえばcommentモデルのbodyフィールドの場合、ブラウザからサーバに渡す形式ってcomment[body]=???の形で渡るので、同じようにpost(create,'comment[body]'=>'??? ')としてみても、サーバー側でparams[:comment]は空。試行錯誤のうち、post(create,:comment=>{:body=>'??? '})が正しいことが判明。この時点で4時近くになっていた。
コメントの投稿と閲覧ができるまでの実装は順調に進み、6時に終わった。

ただ、その時点の状態では、コメントは無限に投稿できるし、コメントの表示も今まで投稿された全部が一画面に表示される状態だった。
これだと本当に最低限すぎて実用性がまったくないのはいやだなーと思い、掲示板作成機能を追加することを画策。
そうなるとBoardモデルが必要になり、いままでのCommentモデルにBoadモデルのリファレンスを追加し、また、掲示板作成画面もどうすんのよ。って話になり、さらには、作成機能があったとしても、掲示板一覧を表示する画面も必要になるよね、やっぱり2chのように1掲示板の投稿を1000件ぐらいに制限する必要もあるよねということで、明らかに残り3時間では無理だと判明。

次に考えたのがページネーション機能。前のエントリにもあったようにJavaScriptでできるフレームワークがあるって思っても、無限に投稿されていくと日々重くなっていくのは、明らか。
素直にページを変える度にサーバにアクセスしてもいいのだが、それだとJavaScriptのフレームワークの大部分を改造する必要がある。ページングするには、全レコード数がでないといけないから、Model.find(:all).sizeみたいなこともしないといけないし、それって軽いんだっけと悩む。select_sqlだと速いのかなー。

どれも制限時間内に無理だと気づいたら、7:30を回っていて、あーこれは最低限の機能のソースを渡すしかないなと思っていたら、なにもこっちでデータをどう絞るか考えなくても、ユーザに選択させればいいじゃんと思いついた。
そこで、自分の作った家計簿の日付選択のライブラリがあることに思いあたり、思いのほか簡単に取り込めた。サーバー側も渡された日付をパースして、find時のconditionに渡すだけ。

すべて完了したのが9時過ぎ。あっという間だけど、永かった。
画面も一画面、モデル、コントローラも1個とかなりしょぼいが、一応実用できるとこまではいったんじゃないかなと思っている。

一応最近得意のgithubに挙げました。
http://github.com/takeshy/commentboard/tree/master

これで面接落ちたら、ショックでかそう。

| | コメント (0) | トラックバック (0)

2009年8月 5日 (水)

JavaScriptでソート・ページネーション対応テーブルを作る。

ページネーションをするのに、Railsではよくwill_paginateが使われるが、前回も言ったように、サーバー側でビューのロジックを書かないといけないのは好きになれない。

なので一度、データをすべてJSONで取得し、クライアント側のJavaScriptでソートやページネーションを行う対応をした。その分、初期表示が遅くなるかもしれないが、1000件ぐらいのデータだと、ものの10秒以内に表示できる。それ以上は表示しても、誰も見ないだろうから問題ないとしている。

ソースはgithubに上げました。
   git clone git://github.com/takeshy/sortable_table_with_pagination.git

  使い方
  table.jsを読み込み、下記のフォーマットでnewする。

 var tableObj = new SortableTable({id:'テーブルを表示するノードの親のID',
    data_set: テーブルデータ※後述
    block_num:1画面最大表示件数
    call_back: 画面描画後に呼び出すフック関数
   });
テーブルデータ
   { option: 出力するテーブルタグに付加する属性(style="width:52em;"など),
     header:[
      {name:'列のタイトル',sort:'ソート種別(number or normal)',width:'列幅'}
             :  ←列の数だけ上記エントリを作成
   ],
     data:[
      [行1、列1のデータ, 行1、列2のデータ,…],
                  :    ←行の数だけ上記エントリを作成
    ]
   }

(例) 本aが290円、本Bが330円,本Cが450円で1画面最大表示レコードが2件の場合

 var tableObj = new SortableTable({id:'book_div',
    data_set:{option:'class=”list”',header:
  [{name:'書籍名',sort:'normal',width:'10em'},
     {name:'金額',sort:'number',width:'6em'}],
     data:[['a','290円'],['b','330円'],['c','450円']]},
    block_num: 2,
    call_back:null
   });

イメージ
Table1_3  

| | コメント (0) | トラックバック (0)

2009年8月 4日 (火)

テンプレート・エンジンが好きになれない。

Webアプリ作成でjspやerbのようなテンプレート・エンジン使うのが好きに
なれません。
プレゼンテーションの処理がテンプレート・エンジンとJavaScriptでごっちゃ
になって複雑になりそうに感じます。
データをすべてjson形式で取ってきて、それをJavaScriptを使って画面に表示
するようにして、プレゼンテーション関連の処理はJavaScriptに統一するように
すればいいのに、と常々思っています。

長所

サーバーの負荷が減る

動的に内容が変わるHTMLではキャッシュが難しいですが、固定HTMLだと
HTMLを書き換えた時以外はキャッシュしたものを使えます。
また、プレゼンテーション周りの処理がクライアントに移る分負荷が減ります。

クライアントの自由度が増す
json形式のインターフェースがすでに用意されているので、表示をFlashに変えた
り、マッシュアップしたりする対応が簡単になります。Webサービスに対応する際
も認証を追加するぐらいで対応できます。

短所

携帯電話のようなJavaScript非対応のブラウザでは表示できない

これは、どうすることもできないですね。こういう場合はerbのような
テンプレートをガンガン使えばいいと思います。

テストが大変

ブラウザのコンポーネントを扱うJavaScriptをテストファーストで書くのは
かなり至難の業。
seleniumもありますが、あのテストを動作前に書くのはかなり効率が悪そう。

私が作ったWebアプリのWeb家計簿では、テンプレート・エンジンを使わず
データはすべてAjaxで反映しています。サーバ側の言語環境であるPythonを
習いたてだったにもかかわらず、機能的には実装しようと思ったものはすべて
実装できました。
JavaScriptが得意だったら、完全Ajaxベースにするのも、ありなのでは?

| | コメント (0) | トラックバック (0)

2009年7月28日 (火)

VIMでマッチしているHTMLタグやrubyの対応するdo endにカーソルを移動させる。

VIMでよく知られている機能にノーマル・モード時に%を入力すると対になった()や{},[]の間をカーソルがjumpできる機能がある。
ただ、この機能はrubyのdo~endやHTMLの<div></div>のようなタグには対応していない。そこで便利なのがmatchit.vimというプラグイン。
実際:help %とヘルプを出すと、下記のように本家本元のヘルプにも記述されているぐらいのお墨つきのプラグインなのだ。
For other items the matchit plugin can be used, see
            |matchit-install|.

matchit.vimのインストール方法

  1. http://www.vim.org/scripts/script.php?script_id=39 から最新のmatchit.zipをダウンロード
  2. 1.でダウンロードしたzipファイルを展開し、展開してできたdocとpluginのディレクトリをVIMをインストールしたディレクトリの配下にあるruntimeというディレクトリ(vim上で:echo %VIMRUNTIMEで表示されるパス)の下にコピー(docとpluginというディレクトリはすでにあるので、そのディレクトリに対して上書きコピー)
    以上

もしヘルプファイルを更新する場合は、vim上で下記のコマンドを実行
:helptags $VIMRUNTIME/doc

HTMLやRubyだけでなく、LaTeX, Lua,Vimスクリプト、VBスクリプト
にも対応しているらしく、初めてmatchitをインストールした人は絶対
「おぉー」て感動するはず。
ただ、欠点もあって、拡張子が.htmlのファイルの中のJavaScriptの{}、()の
%の対応が効かなくなる。拡張子が.jsの場合は問題ないのだが。
おそらく拡張子によって、マッチングさせるキーワードを変更しているのだろう。

2009.08.25 追記
machit.vimはVim6.0以上は最初から添付されているので、わざわざ上記の
URLから取ってきてインストールする必要はない。
.vimrc等に
source $VIMRUNTIME/macros/matchit.vim
の記述をすれば、OK

!注意 
vimrcに記述せず、:source $VIMRUNTIME/macros/matchit.vim
を実行した場合は、今開いているバッファに対しては有効にならないため、
:eなどで再度ファイルを読み込みなおす必要がある。

また、最初から添付されているmatchit.vimの場合は拡張子がhtmlでも
JavaScriptの(),{}等の移動がサポートされている。

| | コメント (0) | トラックバック (0)

2009年7月19日 (日)

Javaの型変換

恥ずかしながら、今更Javaを一から勉強中。
今日は型変換について。

double型にint型の計算結果を代入(1)

 class Test {
  public static void main(String[] args){
    double c;
    int a=2,b=1;
    c=b/a;
    System.out.printf("c=%f\n",c);
  }
}

結果
c=0.000000

double型にint型の計算結果を代入(2)

 class Test {
  public static void main(String[] args){
    double c;
    int a=2,b=1;
    c=(double)b/a;
    System.out.printf("c=%f\n",c);
  }
}

結果
c=0.500000

double型にint型の計算結果を代入(3)

 class Test {
  public static void main(String[] args){
    double c;
    int a=2,b=1;
    c=(double)(b/a);
    System.out.printf("c=%f\n",c);
  }
}

結果
c=0.000000

int型にdouble型の計算結果を代入(1)

 class Test {
  public static void main(String[] args){
    int c;
    double a=2.0,b=1.0;
    c=b/a;
    System.out.printf("c=%d\n",c);
  }
}

結果
Test.java:5: 精度が落ちている可能性
検出値  : double
期待値  : int
    c=b/a;
   ^

int型にdouble型の計算結果を代入(2)

 class Test {
  public static void main(String[] args){
    int c;
    double a=2.0,b=1.0;
    c=(int)b/a;
    System.out.printf("c=%d\n",c);
  }
}

結果
Test.java:5: 精度が落ちている可能性
検出値  : double
期待値  : int
    c=(int)b/a;
            ^

int型にdouble型の計算結果を代入(3)

 class Test {
  public static void main(String[] args){
    int c;
    double a=2.0,b=1.0;
    c=(int)(b/a);
    System.out.printf("c=%d\n",c);
  }
}

結果
c=0

| | コメント (0) | トラックバック (0)

2009年7月16日 (木)

Firefoxの文字がきたない。

Windows xp上のFirefoxの画面上の文字が太さが安定していなくて読みづらいなと
思って早5年。
ひょんなことから、直し方が解かった。
Firefoxの設定ではなく、Windowsの設定だった。

1.デスクトップ上で右クリックし、プロパティを選択。
2.デザインタブをクリック。
3.効果のボタンを押下。
4.次の方法でスクリーンフォントの縁を滑らかにする。の選択ボックスを標準からClearTypeに変更
5.OKで閉じる。

これって常識なのか?

| | コメント (0) | トラックバック (0)

2009年6月27日 (土)

iPhoneで拡張子がepubなのに、このファイルはダウンロードできませんが出力される

iPhoneを買ったので、さっそくThe Pragmatic Bookshelfで買った電子書籍を
iPhoneで読むぞとsafariから
epub (for iPhone, Sony, etc) (516.6 KB)
をクリックすると、このファイルはダウンロードできませんの表示が。
FAQを見ると、Stanzaという無料の電子書籍リーダを入れろとあるので、
入れてみたが、変わらない。
ネットで検索してもそれらしい記述がないので、ちょっと唸ったが、ようやく解かった。

1.Stanzaを立ち上げる
2.オンラインカタログを選ぶ。
3.右下のアイコンの+をクリック
4.Add Web Pageを選択
5.URLにhttp://www.pragprog.com/iphone/downloads/ebooksをセットし、保存

作成したカタログをクリックし、そこからだとdownloadできた。

| | コメント (0) | トラックバック (0)

«vimで特定のファイルの特定行に飛ぶ