2010-12-29

GreasemonkeyスクリプトをChromeに対応させる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
図書館サイトを便利にするGreasemonkeyスクリプトである図書ぶらはFirefoxでしか動かなかったのですが、Chromeでも動くようにしてみました。

今回、Chromeで動かすためにやったことは以下のことです。

(1)jQueryの読み込み方法の変更
chromeで動くGresemonkeyスクリプトでjQueryを利用するを見てください。

(2)クロスドメインでXMLHttpRequestを利用できるようにする
Access-Control-Allow-Originをどこで出力すればよいのか迷ってみたを見てください。

(3)GM_*のラッパー関数を作成
図書ぶらでは、以下のGreasemonkeyで拡張されている関数を利用しています。
GM_setValue
GM_getValue
GM_xmlhttpRequest
これはchromeでは使えないので、以下のような関数を作成しました。
GM_setValue、GM_getValueは以下のような感じです。

function GM_setValue(key,value) {
 localStorage[ key ] = value;
}

function GM_getValue(key,def) {
 if( localStorage[ key ] == undefined && def != undefined ){
  GM_setValue( key , def );
 }
 return localStorage[ key ] ;
}
ここでの注意は、localStorageは文字列しか保存してくれない気配です。
GM_*のときはBooleanはBooleanで保存できていたのですが、localStorageではBooleanを文字列に変換していました。

GM_xmlhttpRequestの方は、完全互換でなくてGM_xmlhttpRequest風な以下のものを用意しました。
function GM_xmlhttpRequest(url,onload){
 var xhr=new XMLHttpRequest();
 xhr.open("get",url);
 onload&&(xhr.onload=function(){onload(this)});
 xhr.send();
}

そんなに使っていないので完全に置き換えてもよかったのですが、なんとなくこんなのを用意してみました。

とりあえずこんな感じでchromeでも動くGreasemonkeyスクリプト(chromeの場合はユーザスクリプトと言った方よいのかな)図書ぶらとなりました。

Access-Control-Allow-Originをどこで出力すればよいのか迷ってみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
今まで、普通のjavaスクリプトで行える通信はjavaスクリプトを読み込んだサイトに対してだけだと思っていました。

以下の図でいうとAから読み込んだHTMLに書かれているjavaスクリプトでXMLHttpRequestを利用して通信できるのはAだけでBとは通信できないという感じです。
|-----|     |-----|
|  A  |     |  B  |
|-----|     |-----|
   |           |
   |           ×
|--------|     |
|ブラウザ|-----|
|--------|

でも、どうやらXMLHttpRequest level2というのではBとも通信できるようになるらしいです。
それもjavaスクリプトの記述の仕方では特に変わったことをする必要はなくAと通信するXMLHttpRequestと同じような書き方でよいそうです。
Bと通信できるようにするには、httpのヘッダーに
Access-Control-Allow-Origin
が出力されればOKとのことです。

で、ここでこのAccess-Control-Allow-Originヘッダを出力するのは、AなのかBなのかよくわからなくなってみましたが、結論としてはBの方でした。

ちなみにGoogle App EngineでAccess-Control-Allow-Originヘッダを出力するには、以下のような感じです。
self.response.headers['Access-Control-Allow-Origin'] = '*'

*の部分は接続を許容する先を記述するところで、*と書くとどこからでもOKということになります。

すべてのブラウザで対応しているわけではなさそうですが、javaスクリプトでできることが増えそうです。

2010-12-27

chromeで動くGresemonkeyスクリプトでjQueryを利用する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
jQueryがステキなのでGreasemonkeyスクリプトでもjQueryを利用しています。

Firefoxだけで動くGreasemonkeyスクリプトでは以下のように書いていました。
(function(d, func) {
    var check = function() {
        if (typeof unsafeWindow.jQuery == 'undefined') return false;
        func(unsafeWindow.jQuery); return true;
    }
    if (check()) return;
    var s = d.createElement('script');
    s.type = 'text/javascript';
    s.src = 'http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js';
    d.getElementsByTagName('head')[0].appendChild(s);
    (function() {
        if (check()) return;
        setTimeout(arguments.callee, 100);
    })();
})(document, function($) {
    //ここに処理を書く
    alert("There are " + $('a').length + " links on this page.");
});

でもこれではChromeでは動かなかったのです。
理由はよくわかりませんが、
unsafeWindow.jQuery
がずっと
undefined
になっているせいのようです。

Chromeでも動くGreasemonkeyスクリプトでjQueryを利用するには以下のように書くとよい感じです。
function addJQuery(callback) {
  var script = document.createElement("script");
  script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js");
  script.addEventListener('load', function() {
    var script = document.createElement("script");
    script.textContent = "(" + callback.toString() + ")();";
    document.body.appendChild(script);
  }, false);
  document.body.appendChild(script);
}

function main() {
  //ここに処理を書く
  alert("There are " + $('a').length + " links on this page.");
}

addJQuery(main);

こちらは動きました。もちろんFirefoxでも動きます。
最初のFirefoxでしか動かない版だと、すでにjQueryが読み込まれていればjQueryの読み込み処理を行わないっぽいのでよい感じなのですが、FirefoxでもChromeでも動くというのを重視することにしてみました。


Railsでグローバルな定数を書くところ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Railsでグローバルな定数を定義する場所を検索したら、
config/environment.rb
に定義すればよいよ。みたいなことが見つかるのですが、
config/environment.rb
には、なんとなく必要となるライブラリとかをRailsのアプリケーションを動作させる
ための環境設定を記述するのがメインでなんとなくしっくりこないなぁとか思っていたところ、
config/initializers/constants.rb
というファイルを作って、これに定義するのもよいというのを見つけたので、こちらで利用することにしてみました。
定数だけを記述しているというのがなんとなく役割がはっきりしていて気に入りました。

config/initializers/constants.rb
にはモデルでもコントローラーでも利用することがある定数を定義することにしてみました。
コントローラーだけで利用するならば、
ApplicationController
に定義して、
モデルだけで利用するならば、定数を定義したモデルclassを用意して、それを継承するのがいいのかなぁとか思ってみました。

2010-12-24

Windows 7では管理者権限を持つユーザを2つ作っておくのがよい感じ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Windows 7を利用してログインしようとしたら

「User Profile Serviceサービスによるログオン処理に失敗しました。ユーザープロファイルを読み込めません」

と言われてログインできなくなりました。
過去にも一度、同じようなことになったことがあります。

これを直すには、
http://ameblo.jp/bomber1129/entry-10687686009.html

にあるように管理者権限がある別のユーザでログインして
システムの復元
をすれば再度ログインできるようになります。

管理者権限を持つユーザがひとつしかない場合、この情報を検索することもできません。
本当に急にログインできなくなるので、もしもに備えてWindows 7では、管理者権限を持つユーザを2つ用意しておいて、仮に管理者権限のユーザでログインできなくなってもなんとかなる状態にしておいた方がよい感じです。

2010-12-16

可変長プレフィックで重複が発生しないようにチェックするためのSQL

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
題名がよくわからない感じになってしまいましたが、内容としては以下のような感じです。

あるコード体系が
XXXXYYYY
のようになっていて、XXXXが親コードをあらわしてYYYYがその枝番を表しているようなコードがあり、さらにXXXX部分が固定長でないという既存コードをそのまま使いたいというケースです。
例えば、
親コードが
101
2001
とかになっていて
枝番も付与すると
10100001
20010001
みたい担っているコードです。
このような親コード部分をプレフィックスと今回、呼ばせてもらったのですが、このプレフィックス部分は、上記の例の場合
200(この枝番に2001が含まれる可能性があるため)---ケース1

1011(101の枝番とかぶる可能性があるため)---ケース2
も登録したくありません。

これをチェックする方法です。
MySQLのテーブルにプレフィックスが登録していあるとします。
テーブル名:pre
code
101
2001

まずは、ケース1をチェックします。
こちらは簡単。
select * from pre where code like '200%'
これで1件でも引っかかれば登録できないものとします。

ケース2の場合は以下のような感じです。
select * from pre where '1011' like concat(code,'%')
これで1件でも引っかかれば登録できないものとします。
こちらはデータ件数が多くなると遅くなるような気がするので注意が必要かもです。

上記2つをorで結合して以下のような感じで一気にやるのがよいかもしれないです。
select * from pre where code like '1011%' or '1011' like concat(code,'%')

2010-12-08

土偶の本

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
土偶ってすごく生命力あふれる感じがとてもステキなのです。

そんな土偶をいっぱい見ることができる本なのでオススメです。







個人的な好みとしては、縄文のビーナスと言われるいる土偶やみみずく型土偶とかが特にお気に入りです。
縄文後期の遮光器土偶や埴輪とかの中空のものもステキなのですが、なんとなくワイルド感というか力強さが若干ものたりないと思ったりしているのです。

2010-11-30

ActiveScaffoldでNestedを使ったらエラーが出たよ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
RailsのScaffoldをステキにする
ActiveScaffold
を使っています。

ActiveScaffoldは、以下のページで記載されているようにすることで管理画面をネストすることができます。
https://github.com/activescaffold/active_scaffold/wiki/API%3A-Nested

でもRails2.3で利用すると以下のようなエラーが出て利用できませんでした。
ActionView::TemplateError (undefined method `render_component' for #<ActionView::Base:0xb76b7224>) on line #39 of vendor/plugins/active_scaffold/frontends/default/views/_nested.html.erb:

調べたところ、render_componentというのが2.3では利用できないようで以下のように別途pluginを追加する必要があるようです。
script/plugin install git://github.com/ewildgoose/render_component.git -r rails-2.3

と以下のページに書いてありました。
http://code.google.com/p/activescaffold/issues/detail?id=685

これで無事にネストを利用することができるようになりました。
ステキなActiveScaffoldです。

2010-11-23

ubuntuをEee PC 1018Pに入れてみた

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Eee PC 1018Pを持っているのですが、ハードディスクが相当あるのでいろいろマルチブートにして遊んでみようと思ったのです。

とりあえず190Gぐらいの何も使っていない領域を開放しました。

まずはお手軽にubuntuをいてみようと思ったのですが、思った以上に苦戦してしまいました。

CD-ROMなどはもう手元にないので、USBメモリを利用してインストールしようと思ったのですが、いろんなやり方を試しても
busy box
と表示されてしまいます。
このように表示した場合の対処もいろいろ検索できるのですが、どれもうまくいかず。

確証はないのですが、どうも途中でCDROMがないのに探しにいっている感じで、USBメモリを見失っているような感じです。

最終的には、コチラ
http://ubuntu10144.blog111.fc2.com/blog-entry-15.html
に書いてある方法を参考にAlternate版というものをダウンロードして
こちらを利用してLANに接続した状態で、インストーラーからネット経由で各種ファイルを取得する形でインストールを行うことでなんとか動くようになりました。

ちなみにAlternate版はコチラから取得しました。
http://ftp.riken.jp/Linux/ubuntu-iso/CDs//10.10/

とりあえずインストールが完了して、最初に動かすと無線LANも認識してくれたので、このドライバをネットからダウンロードできたらLAN接続は解除して利用しています。

2010-11-17

rubyを1.8.7から1.9.1にしてみたときのメモ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
rubyが1.8.7で
railsが2.3.5でアプリを作ったアプリをRails3も出ているこのご時勢なので
ちょっとアップデートを試みました。

Rilas3にするのは大変そうな気がしたので、
まずは、railsを2.3.5から2.3.10にアップデート。
こちらはそんなに困らずにアップデートできました。

そしてrubyを1.8.7から1.9.1にアップデートするために
rvmをインストールして複数のバージョンを利用できるようにしました。

rubyを1.9.1にアップデートするには、以下の対応を行いました。
(1)日本語対応させるためのマジックコメント追加
テストを行うと
invalid multibyte char (US-ASCII)
みたいなエラーが出てテストができない状況だったので、
とりあえず各ファイルに以下のようなマジックコメントを追加しました。
# -*- encoding: UTF-8 -*-


(2)FasterCSVの利用をCSVに変更
CSVの処理を行う部分があり、FasterCSVを利用していたのですが
1.9にはFasterCSVが普通にCSVとして組み込まれているようなので
FasterCSVの部分をCSVに置き換えました。


(3)mysqlの接続アダプターの変更
テストを行うと
incompatible character encodings: ASCII-8BIT and UTF-8
みたいなのがたくさん出てきました。
マジックコメントを入れたので日本語対応が済んでいると思ったのですが、
ActiveRecordの結果がいまいちな感じでした。

実際調べてみまたところ、アクティブレコードの出力が確かにASCII-8BITになっていました。
#ファイルで適用されているエンコーディングを出力
p __ENCODING__
Encoding:UTF-8
#アクティブレコードで取得したレコードのエンコーディングを出力
p n[:aaa].encoding
Encoding:ASCII-8BIT
#念のためソースに記載した日本語のエンコーディングを確認
p "あああ".encoding
Encoding:UTF-8

ruby 1.8.7では
gem install mysql
としてmysql用のアダプターを入れていたのですが、どうもこれはだめなようで
ruby-mysql

mysql2
を使う必要があるようです。

単純に移行するならば
ruby-mysql
の方がちゃんと互換性があるようです。
使うときは、以下のように既存を削除して追加する必要があります。
gem uninstall mysql
gem install ruby-mysql

mysql2の方が速いらしいし、Rails3ではこれをつかうっぽいので、
こっちを使ってみることにしてみました。
使うときは、以下のように既存を削除して追加する必要があります。
gem uninstall mysql
gem install mysql2

そしてconfig/database.ymlのadapterを
adapter: mysql2
とする必要があります。

ちなみにnum_rowsを使って検索件数を取得していたのですが、
mysql2にはないのでcountに置き換えました。

だいたいこんな感じで1.9.1の対応ができました。

ちなみに1.9にするとスピードもあがるとのことなので1.8.7のときと1.9.1のときの同じテストを行ったときの時間を参考までに。

1.8.7 Finished in 270.402445 seconds
1.9.1 Finished in 218.353968929 seconds

確かに速くなっています。

2010-11-10

大量のデータをActiveRecordで処理するとき

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Railsで大量のデータを処理するときです。

何も考えずに
User.find(:all,:conditions=>"age > 18").each do |u|
 #なんか処理
end
みたいなことをやっていました。

データが増えるとメモリがえらいことになってしまいました。

そんな時は、
User.find_each(:conditions=>"age > 18") do |u|
 #なんか処理
end
みたいにするとメモリの利用を削減できます。

以下が参考になります。
ここではRails3の説明となっていますが、2.3の新しいめのバージョンならば使えるようです。
http://wiki.usagee.co.jp/ruby/rails/RailsGuides%E3%82%92%E3%82%86%E3%81%A3%E3%81%8F%E3%82%8A%E5%92%8C%E8%A8%B3%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E3%82%88/Active%20Record%20Query%20Interface#i803e697

2010-11-07

「図書ぶら」というのを作ってみました

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
図書館サイトの検索結果ページに、その本に関連する本のリストとAmazonへのリンクを追加するGreasemonkeyスクリプト「図書ぶら」というのを作ってみました。

私は、図書館をよく利用しています。
探す本がわかっているときはいいのですが、なんとなく本を探したいというときには、図書館サイトはむかないつくりになっています。
amazonさんの場合は本に関連する本を紹介してくれるので、参考にしちゃっています。
なのでそのamazonさんの関連本を図書館サイトの方にも表示させるようにしたら便利かもしれないと思い作ってみたのが「図書ぶら」です。

図書館で本を使う方は使ってみていただけるとうれしいです。

現在は、東京23区だけの対応になっていますがご要望があれば他の図書館にも対応したいと思っています。

ちなみに関連本を表示するためには、
Amazon Product Advertising API
を使っています。
その関連本が、その図書館に存在するかを調べるために
カーリル | 図書館API仕様書
を使っています。
これらのAPIはGoogleAppEngine上に作成したアプリがProxyして要求をかけています。
以下のような感じです。
図書ぶら-->GoogleAppEngine-->Amazon,カーリル

2010-11-06

GreasemonkeyスクリプトでGM_getValueをイベントで使おうとしたら

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Greasemonkeyスクリプトを最近、いじってあそんでいます。
GM_getValueというデータを永続化しておくことができるGreasemonkeyの関数があるのですが、
これをクリックイベントの中で使おうとしたら

Error: Greasemonkey access violation: unsafeWindow cannot call GM_getValue.

とエラーが出てしまいました。

イベントの中で普通にこのように書くとダメなのです。
 var value = "bar";
 GM_setValue("foo", value);

でも、以下のように書くとOKになります。
  var value = "bar";
  setTimeout(function() {
    GM_setValue("foo", value);
  }, 0);
setTimeoutでくくればOKなようです。なぜかはよくわかりません。

ちなみに
http://wiki.greasespot.net/0.7.20080121.0%2B_compatibility
に書いてありました。

2010-10-25

ActvieDirectoryでケルベロス認証して、その結果をrailsで使ってみる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
railsには便利な認証機構がいろいろある感じですが、ActiveDirectoryに認証を任せるには普通はldapを使うのでしょうが、都合によりActiveDirectoryのldapがうまく使えないためケルベロス認証させたいときお話です。

調べ見たところ、もうそこはrailsではなくapacheの方でmod_auth_kerbを利用して認証させて、その結果がREMOTE_USERに設定されるので、その値を利用して認可するというやり方をするようです。
このやり方であればapacheのモジュールで認証できる仕組みならば、rails側に持ってくることもできそうです。

なので使えるようにしてみました。
環境は、CentOS5.4,apache2.2,passengerを利用した環境です。
ちなみにpassengerを使わずにapacheをproxyにして別のwebサーバを利用している時は、mod_rewriteを使ってREMOTE_USERが後ろのサーバに伝播されるような設定が必要なようです。

まずは、mod_auth_kerbの準備です。
[/etc/krb5.confの設定]
http://junsan45.blogspot.com/2009/10/centos-53-windows.html
などを見て、環境にあわせて/etc/krb5.confを設定してください。
ここで設定したrealmの値を後で使います。

[インストール]
su
yum -y install mod_auth_kerb

[設定]
vi /etc/httpd/conf.d/auth_kerb.conf
とりあえずテスト用に以下のような感じで設定
-----------------------------
<Location /test_krb_auth>
AuthType Kerberos
AuthName "Kerberos Login"
KrbAuthRealms [/etc/krb5.confで設定したrealm]
KrbVerifyKDC Off
KrbMethodNegotiate Off
require valid-user
</Location>
-----------------------------

[確認]
これで対象のサイトにログインした際に
これでREMOTE_USERに
username@realm
のようにrealm付きで認証したユーザがセットされることをお手軽に確認できる方法で確認します。

[おまけ]
mod_auth_kerbのversionが5.4
ならば
KrbLocalUserMapping On
とすることで
上記の@以降のrealmが除去される模様です。
yumでインストールされるversionは5.4より古かったです。


ここでrailsアプリを用意してpassengerの設定を行います。
passenger.confに以下のような感じでrailsアプリを利用できるように配置します。

RailsBaseURI /rails_kerb

<Location /rails_kerb>
AuthType Kerberos
AuthName "Kerberos Login"
KrbAuthRealms [/etc/krb5.confで設定したrealm]
KrbVerifyKDC Off
KrbMethodNegotiate Off
require valid-user
</Location>

これでrailsのApplicationControllerで
login = request.env['REMOTE_USER']
でユーザ情報を受け取り、データベースでも見て利用可能なユーザかどうかをチェックすればOKです。

本番環境はこれでよいのですが開発環境ではwebサーバでapacheを利用することはあまりないと思うので、REMOTE_USERが取得できないというのが困った感じです。
とりあえず以下のような感じで環境がdevelopmentの時だけ、独自のBASIC認証をしてREMOTE_USERをセットするようにしてみました。

class ApplicationController < ActionController::Base
  before_filter :authorize
  protected
  def authorize
    auth_ret = true
    if session[:user].nil?
      if ENV['RAILS_ENV'] == "development"
        auth_ret = false
        authenticate_or_request_with_http_basic do |user, pass|
          request.env['REMOTE_USER'] = user
          true
        end
      end
      login = request.env['REMOTE_USER']
      //本当はここいら辺でloginを利用して値をチェック
      session[:user] = login
    end
    if auth_ret and session[:user].nil?
      //認可されなかったときの処理
    end
  end
end
auth_retは、
if ENV['RAILS_ENV'] == "development"
の中に入るけど
authenticate_or_request_with_http_basic do |user, pass|
の中に入らない動きを見せたので入れてみました。

これでdevelopment環境でもREMOTE_USERが設定されるようになりました。
test環境を加えてもよいのかもしれないです。

2010-10-24

javascriptで前後の空白を除去する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
javascript 空白除去
で検索するといろいろ出てくるのですが、前後の
全角スペース、半角スペース、タブ、改行
すべてを除去してくれるものは見つからなかったので、組み合わせてメモ的に書いておきます。

こんな感じです。
val = unescape(escape(val).replace(/^(%u3000|%20|%09|%0D|%0A)+|(%u3000|%20|%09|%0D|%0A)+$/g, ""));

valが前後の空白を除去したい文字列です。

2010-10-21

jQueryでいくつかの画像を順番に表示するプラグイン

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
説明画面のようなものを画像を使って作りたいなぁと思ったわけです。

古くはアニメーションGIFなんぞを使ったのかもしれませんが、メンテナンスが面倒そうです。
今どきならば動画を用意するのがよいかもしれませんが、そこまでするほどの内容でないのです。

困った時のjQueryということで探したところ、
Feature List
というプラグインを見つけました。

こちらのページを見て見つけたのでした。
http://phpspot.org/blog/archives/2009/12/jqueryfeature_l.html

具体的な使い方は、上記のページを参考にしてください。

Feature Listを使う際には、
idがtabsとoutputというulタグでくくられたリストを用意します。
(実際は、tabsとoutputでなくてもよいのでしょうが例がそうなっているので。)

で実際には以下の2つの動作が行われます。
(1)idがoutputであるulタグで囲まれたliタグのリストを先頭から順番に表示
(2)idがtabsであるulタグで囲まれたliタグのリスト直下のaタグに先頭から順番にcurrentクラスが移動

なのでidがoutputであるulタグ内のliタグ内にimgタグを書いておけば画像が順番に表示されることになります。仕組みとしてはliタグの中が順に表示されるので別に画像でなくて普通に文章でも問題なしです。
idがtabsであるulタグ内のliタグリストは常に表示されます。currentクラスが順についていくのでcssでcurrentクラスを定義することで見た目を変えていくことになります。

かっこよさげに表示させるには、上記をふまえてcssをちゃんと書くことが重要です。
cssを何も書かないと相当かっこ悪いです。

cssでは最低限、以下ぐらいは入れないとかっこ悪い感じです。
実際はサンプルをちゃんと見たほうがよいです。
div#feature_list {
 height:800px;
}
div#feature_list ul {
 list-style: none; 
}
ul#tabs li a.current {
 color: red;
}
ul#output li {
 position: absolute;
}
div#feature_listのheightは実際に使うサイズにしてください。
div#feature_list ulのlist-styleがnoneでないと・とかでます。
ul#tabs li a.currentは単なる一例です。
ul#output liのpositionがabsoluteでないと当たらし表示が出るときにカクカクします。

cssをちゃんといじればかっこよくなるので、今後も使いそうなjQueryプラグインな気がします。

2010-10-08

Google App Engineのwebappでステータス404を返す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
python版のGoogle App Engineで提供されているフレームワークであるwebappでhttpのステータスコード404を返したいなぁと思って調べたら、
class AaaPage(webapp.RequestHandler):
  def get(self):
    self.error(404)
    return self.response.out.write('404 not found')
というパターンと
class AaaPage(webapp.RequestHandler):
  def get(self):
    self.response.set_status(404)
    return self.response.out.write('404 not found')
という二つのパターンが見つかります。

何が違うのかしらん?と思っていたらgoogleさんに普通に書いてありました。
http://code.google.com/intl/ja/appengine/docs/python/tools/webapp/requesthandlerclass.html#RequestHandler_error

self.error(code)

self.response.clear()

self.response.set_status(code)
を呼び出した場合と同じだそうです。

なので違いは、
self.response.clear()
を呼ぶか呼ばないかみたいです。
self.response.clear()
を呼ぶ場合と呼ばない場合でどんな違いがあるのかよくわからんので
とりあえず呼んでおくことにして
self.error(code)
を使うことにしてみました。

2010-09-22

ユニフィール

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


メモをぷすぷすとさしてためていくメモフォルダーです。
なんかこういうのが一個あってもいいかなぁとキニナルのです。

レシートをぷすぷすさしてためておくのもよい感じとのことです。

ペン型カメラ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク



ペン型カメラです。
商品としては、面白いとは思うのでキニナルのですが、使い道を考えるとやっぱりとってはいけないものをこっそりとるためという感じですよね~~。
どうどうと取れるならば、今ならば携帯で取れますものね。
そしてamazonの評判を見ると壊れやすい感じなのもちょっと残念な感じです。
でもキニナルのでした。

2010-09-08

Google App EngineでPORTAのAPIを使ってみようと思ったけど・・・

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
PORTAとは、国立国会図書館デジタルアーカイブポータルです。
こちらがAPIを提供してくれており、詳しくは以下を見てください。
http://porta.ndl.go.jp/wiki/Wiki.jsp?page=%E5%A4%96%E9%83%A8%E6%8F%90%E4%BE%9B%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

PORTAを使うとamazonとは違う感じの情報が取れないかなぁと思いGoogle App Engine(の開発環境)でAPIを試してみたところ、残念ながらタイムアウトになってしまいデータが取れなかったのです。

試したプロトコルは、OpenSearchです。
これが帰ってくる情報に結構いろいろのっている感じでよさげだったもので。
ちなみにISBNで検索するならば以下のような感じです。
http://api.porta.ndl.go.jp/servicedp/opensearch?isbn=9784334975586
戻りデータは、RSSですが拡張していろんな情報がのっています。

やろうとしたことは、図書館の分類方法のNDC(日本十進分類法)でデータを検索です。
こちらで検索するとなんかISBNとかがのってないような資料もいっぱいひっかかってしまいました。
比較的ISBNが付いているようなデータが戻ってくるようにするには、ジャンルを限定すればよい感じでした。これでもすべてのデータにISBNが付いているわけではありませんでしたが。

ちなみに試したのは、以下のような感じです。
NDCが588で始まるもの一覧です。
ジャンル指定は、dpidで指定しますがzomokuを指定するとよい感じでした。
http://api.porta.ndl.go.jp/servicedp/opensearch?ndc=588&dpid=zomoku

ちなみにndcは、588.xxxみたいに.以下も付いたりするのですがndcで指定できるのは先頭3桁までのようです。

もうちょっといじってみたかったけど、Google App Engineでタイムアウトといわれてしまうとイカんともしがたい気がするので、とりあえず断念してみる。

2010-08-20

Boogie Board

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


ブギーボードというようです。
電子ペーパー的なもののようです。
なんかキニナリます。

こんな紹介記事もあります。
http://k-tai.impress.co.jp/docs/column/todays_goods/20100419_361467.html

冷静に考えれば、子供の磁石のお絵かきボードとあんまり変わらない気もしなくはないのです。


これがもし保存できてPCなりスマートフォンなりに転送できるようになれば、相当いい感じなのでは?
って気がしなくもないです。

2010-08-18

マリンブラ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

これもキニナル楽器です。
でっかい座れるカリンバ?って感じです。
低音のベースとして使われる楽器らしいです。

カホン

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


見た目はイスです。
でも打楽器なのです。
中に弦が入っていたりするようで音がちょっとシャカっとした感じになるようです。

なかなかいい感じなのでキニナルのです。

お値段的には、1万円以上するのが普通なようです。

見た目だけで考えたら、
作れるような・・・
って気がするのです。

で調べ見ると自作に関するページが結構あったりします。
以下がそんな感じです。
http://www.zoscajon.com/netemate/
http://bonzo.blog45.fc2.com/blog-entry-140.html
http://namahage.s53.xrea.com/cajon.html

さらに調べてみるとキットを売っていたりもするようです。

とりあえず作ってみたくなっています。

Martin 「BackPacker SteelStrings」

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


う~~ん、かっこいいギターです。
ギターが弾けるわけではないのですが、なんとなくキニナリ欲しくなってみたりしました。
この細みな特殊な形いいですねぇ~~。
ちなみにAll Aboutで紹介している記事で知りました。

MVPen

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://www.mvpen.com/products/



実は結構、昔から形をあるような気がする電子ペンといわれるものです。
紙に書いたものをPCに取り込めちゃうというものですね。
なんかこれがすごいなぁと思うのが、必要なものの少なさですね。
ペンそのものとよくわからない受信ユニットみたいなのがあればOKという感じです。
ペンも実用的な大きさなような気がします。
お値段も思ったよりかは高くないような気がするのです。なんとなくこういうのって3万ぐらいするのかなぁと思っていたもので。
そんなことで買ってしまったのです、結構ちゃんと認識してくれて持ち運びも楽なのでオススメです。

私の場合は、PCで作業していることが多く紙に書くことがすごく少ないので利用することはまれだったりするのですけどね。

プスプス

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://www.babycar.co.jp/



プスプスは、東京乳母車が発売しているベビーカーです。
まさに乳母車です。
籐バスケットを使っていてとてもおしゃれでキニナルのです。
正直、値段は高いなぁと思います。
でも、おしゃれで素敵です。
思うに、電車で移動しても使うならば、普通のB型ベビーカーじゃないときついのでしょうが、家の回りでいろいろ用が済んでしまう都心の人にはいいかもしれません。
大きくみえますが、床面積的にはA型ベビーカーと変わらないらしいですよ。
プスプス赤ちゃんにとっては、ひろびととしてて快適な感じですからね。
調べてみると双子ちゃん用に購入される方も多いみたいですね。
ベビーカーって子供が大きくなると邪魔な存在になるわけですが、このプスプスであればおしゃれなので大きくなって使わなくなっても家の中でおもちゃ箱として使ってもいいのかもしれませんね。

FREITAG

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
http://www.freitag.ch/japan/



フライターグと読むようです。
日本ではあんまり見ない感じですが、トラックのほろをリサイクルして作られているバックなわけです。
ビニールな感じの質感なのですが、リサイクルしたせいか、ちょっと新品でない感じの質感がなんかいい感じなバックなのです。
リサイクルなわけなので同じ柄がないというのがまた魅力だったりします。
形としては、メッセンジャーバック的なものが多いのようですが、そのサイズはいろいろあるようです。個人的には小ぶりなものがいいなぁと思ったりしています。財布などもちょっと気になったりします。
前はたまにどっかで見たぐらいだったのですが、最近は売っているところが増えたような気がします。


>
楽天でも購入できるようになっていたりします。
そして、この商品に関する本も出ているようです。そこがこの商品に対する愛着を持った人が多い感じがしてキニナルわけでもあります。
お値段的に少々するのがちょっとお高めな感じなのでお気軽に買えない私なわけです。

jQueryでおしゃれに画像を並べる

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
画像を並べたいなぁと思ったわけです。
WEBページで何かやりたいことがあるときは、まずはjQueryをキーワードに検索語に混ぜる今日この頃なのです。

jQueryで画像をならべるイメージギャラリー的なものはいろいろあります。
たいていは、きれいに並べておいてクリックすると大きくなるという感じです。

今回は、特に大きくなる必要はなく、狭い範囲でいい感じで画像が並べばよいと思ったわけです。
そんな感じで見つけたのは、
jQuery Image Scroller
です。
画像がある範囲でスクロールしたおす感じです。
なかなか悪くありません。デモもあるのでどんな感じかはそちらを見ていただけたらと思います。

改造はちょっとめんどくさいです。
提供されているcssやjavascriptに直接手を入れるしかないです。

でも、あまり他では見たことがないパターンなので覚えておいて損はないと思います。

クラフトロボ

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


一見するとプリンタに見えますが、カッティングマシンというものです。
印刷するのではなく、紙を切るのです。
なので細かい切り絵とか精密なカットとかが簡単にできるようなのでキニナルのです。
正直とても欲しいのですが、買って何を作るという目的は今のところなしです。
なのでちょっとお値段的に手を出せずにいます。
これよりも安い簡易版があるのですが、切れる紙に制限があるようでちょっと楽しみが減っちゃう感じです。
うーむどうしよう・・・

2010-08-11

pythonさんでAmazonのRSSからASINを取り出す

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
Amazonさんでは、カテゴリごとに売れ筋を紹介するRSSを提供しています。
どんな感じのURLになっているかは、
http://www.ajaxtower.jp/googleajaxfeed/sample/index3.html
を参照してください。

でも、RSSでは商品のタイトルとそのページへのURLは取れるものですが、他の情報は記事みたいな感じでごっちゃでしか取得できません。
個別にいろいろな情報を取得するためには、APIを利用すればよいのですがそのためにはASIN番号があると便利です。
ASIN番号はURLに埋め込まれていますので、これをpythonさんで取得します。

pythonのRSSのパースには、feedparserが便利な感じです。
RSSをパースしてASINを取り出すのは、以下のような感じです。
import re
import feedparser

#取得したカテゴリのRSSを指定
url = "http://www.amazon.co.jp/rss/bestsellers/books/492352/ref=pd_ts_rss_link"
result = feedparser.parse(url)
for e in result.entries :
  pattern = "^.+\/dp\/(.+)\/ref=.+?$"
  p = re.compile(pattern)
  m = p.search(e.link)
  asin = m.group(1)
  print asin

ちなみにカテゴリのRSSに入っている番号はAPIでBrowseNodeで取り出せる番号です。

2010-07-30

pythonさんでIPアドレス帯からキャリアを判別する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
pythonさんでキャリアを判別するためにIPアドレス帯の取得を以下を参考にさせていただいています。
http://d.hatena.ne.jp/tomisima/20070903/1188836400

こちらは各キャリアの利用IPアドレス紹介ページをパースすることで取得しています。
こちらで紹介しているDocomoをパースする部分は
return [ip for ip in re.findall(r'<li>([\d\./]+)%lt;/li>', content, re.M)]
となっているのですが、時折Docomoさんのページでは、
  • 202.229.176.0/24 (2010年7月上旬に追加予定)


  • のようにliタグの間にIPアドレス情報以外の文字が入っているとその部分は取得されません。

    なので以下のように私はしてみています。
    return [ip for ip in re.findall(r'<li>([\d\.]+/[\d]+).*</li>', content, re.M)]

    これで文字が入っていても取得できます。
    ただし未来の追加の部分もとってしまったりします。

    この取得したIPアドレス帯情報を利用してキャリア判別をしています。

    2010-07-09

    Windows 7にアップグレード

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    今までVistaを使っていました。

    Vistaの遅さにはすごくイライラずっとしていて、とうとう我慢できずにWindows 7にアップグレードしました。


    今までの設定を継承させる形でアップグレードしました。
    アップグレード自体は3時間程度かかり、ちょっとイラっとしてみました。

    継承できなかったのは、メールだけですが別途WindowLIVEメールを入れたら
    完全に継承できました。
    メールソフトは今までつけていたのだから付けておいてもらいたいなぁと思ったりします。
    デフォルトで入らなくてもいいけど、今まで使っていたらアップグレードするぐらいはしてもらいたい感じです。

    アップグレードしてWindows7にしてみると動作は快適です。
    特にVistaのFirefoxはたまに恐ろしく遅くなることがあったのですが、Windows7でのFirefoxはそこまで遅くなる感じはないです。

    アップグレードの値段がもっと安ければ、とっくにアップグレードしているのに・・・
    という感じです。

    2010-06-21

    javascriptで配列内に値が存在するかチェックするにもjQueryが便利

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    javascriptで配列内にある特定の値が存在するかチェックしようと思ったわけです。

    var otomo = ['inu','saru','kiji'];
    とあった場合、配列otomoが値'saru'を持つかを確認するような感じです。

    rubyなどではindexを使えだけなのですが、javascriptではこのindexに相当するような関数がぱっとみ見つかりませんでした。
    でも困ったときのjQueryということでjQueryのほうを調べたら
    inArray
    があるということがわかりました。
    $.inArray("saru", otomo)
    みたいな感じで使えます。

    詳しくは、以下を見てみてください。
    http://f32.aaa.livedoor.jp/~azusa/?t=ajax&p=jquery_utilities_array_object_operations#a_jquery_utilities_inarray


    2010-06-20

    ルクエ

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    電子レンジでいろんな料理ができるシリコンでできた、ちょこちょこテレビで見かけるあれです。



    前からキニナルわりには、商品の名前をぜんぜんおぼえていなかったのです。

    ルクエを使ったレシピを紹介してくれるブログもあるようです。
    http://www.lekue.jp/

    そしてルクエを使ったレシピ本もあるところが人気がある感じもしてキニナルのです。

    ボールウィスク

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


    ちょっと見た目がなんじゃらほい?なモノですが、泡だて器だそうです。
    一番の特長は、洗いやすい!ということのようです。泡だて器って確かに洗うのがちょっと面倒なのでキニナル一品なわけです。

    pythonさんでジオコーディングと逆ジオコーディング V3

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    以前、
    pythonさんでジオコーディングと逆ジオコーディング
    というのを書きましたが、いつまにかGoogle map apiがV3になっていました。

    V3になって、Google Map APIを利用するためのキーが必要なくなりました。
    なので、V3版で場所の名前から緯度経度取得するジオコーディングとその逆をpythonでやってみました。

    Google map api V3でのジオコーディングに関しては、
    http://code.google.com/intl/en/apis/maps/documentation/geocoding/
    に書いてあります。

    コードは以下のような感じです。
    google app engineで利用することを前提にしているので
    urlfetchを使っていますが、そうでないならばそこを置き換える必要があります。
    jsonのパーサーも場合によって変更が必要だと思います。

    import urllib
    from google.appengine.api import urlfetch
    import django.utils.simplejson as json
    
    from django.conf import settings
    
    #場所名から緯度経度取得
    def geocoding(addr):
        url = 'http://maps.google.com/maps/api/geocode/json?'
        url = url + '&language=ja&sensor=false®ion=ja'
        url = url + '&address=' + urllib.quote(addr.encode('utf-8'))
        result = urlfetch.fetch(url)
        if result.status_code != 200:
            return None
        obj = json.loads(result.content)
        if obj["status"] != "OK":
            return None
        ret = {}
        ret['lon'] = str(obj["results"][0]["geometry"]["location"]["lng"])
        ret['lat'] = str(obj["results"][0]["geometry"]["location"]["lat"])
        return ret
    
    #緯度経度から場所名取得
    def regeocoding(lat,lon):
        url = 'http://maps.google.com/maps/api/geocode/json?'
        url = url + '&language=ja&sensor=false®ion=ja'
        url = url + '&latlng=' + str(lat) + ',' + str(lon)
        result = urlfetch.fetch(url)
        if result.status_code != 200:
            return None
        obj = json.loads(result.content)
        if obj["status"] != "OK":
            return None
        addr = None
        for result in obj["results"]:
            if "sublocality" in result["types"]:
                addr = result["formatted_address"]
                addr = addr.replace(u'日本, ', '', 1)
                break
        return addr
    


    2010-06-10

    mysqlで4月始まりの年度情報などを得るためのsql

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    mysqlで4月始まりの年度情報を得るsqlです。
    2010年3月でも2009が欲しいという場合のときに使います。

    select case when month(now()) > 4 then year(now()) else year(now())-1 end;

    now()のところを適宜書き換えてください。

    また、指定日が第何四半期にあたるかを得るsqlです。
    4月~6月を第1四半期、1月~3月を第4四半期としたい場合です。

    select quarter(now() -interval 1 quarter)

    now()のところを適宜書き換えてください。

    2010-06-06

    JapaninoのPOV用データをテキストから作る

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Japaninoとは、大人の科学vol.27のおまけのArduino互換8bitマイコンです。



    大人の科学vo.27ではPOVと言われる光残像で文字を書くキットが付属しています。
    なかなか楽しげなのですが、ちょっと面倒なのが文字データを作ることです。
    なのでテキストからこのJapaninoのPOV用データを作成するものをつくってみました。

    Txt2Pov

    使い方は、
    テキストボックス(ABC)と書いてあるところに好きな文字(10文字まで)を入れてデータ作成のボタンを押します。
    すると作成されたPOVデータイメージが表示されます。
    あわせてテキストエリアにPOV用データが表示されます。

    POV用データイメージはクリックすると反転して微調整できます。
    テキストエリアのデータをコピーしてJapaninoのPOVサンプルデータのデータ部分を書き換えればOKです。

    やっていることはActionScriptで、
    ・テキストを画像に変換
    ・変換された画像をピクセル単位で解析
    をしてデータを作成してます。
    抜粋版のソースを、
    http://wonderfl.net/c/aBqZ
    に置いておきました。

    Txt2Povは、Japanino用のデータになっていますのが、http://wonderfl.net/c/aBqZを書き換えれば他のデータ形式のものを作成できると思います。

    本当は、サーバー側にテキストデータを投げれば、POVデータが帰ってくる感じのWebサービスをGoogle App Engine上で創ってみようと思ったのですが、Google App Engineに用意されている画像操作系の機能ではちょっとできそうもない感じでした。
    自前でサーバを持っていればPHPとかで比較的容易に実装できそうな感じではあります。

    次は、HTML5でいろいろできる感じだと思ったので、Javascriptで実装しようと思ったのですが、
    画像操作系のやり方がいまいちわからず挫折。
    というわけでflashでやってみました。

    2010-06-01

    InfiniDBを使ってみる

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    InfiniDBは列指向型DBと言われるもので、データウェアハウスなどの大量データの扱いにすぐれているようです。

    特長は、mysqlのストレージエンジンとして実装されていて各種sqlでデータ操作ができるということです。
    なのでアプリケーションは作りやすいそうな感じです。

    詳しくは、
    http://www.infinidb.org/
    をご覧ください。

    というわけで試してみました。

    CentOS5.4(32bit版)へインストールしてみました。
    手順は、以下のような感じです。

    ルートで行います。
    su

    boostというものが別途必要な感じです。
    yum install boost

    ダウンロードしてインストールします。
    wget http://infinidb.org/downloads/doc_download/203-105-final-32-bit-rpms
    tar xvzf 203-105-final-32-bit-rpms
    rpm -ivh calpont*.rpm

    すでにmysqlが動いている環境にインストールしたので利用ポートの変更とutf-8の設定を行います。
    vi /usr/local/Calpont/mysql/my.cnf
    3306としている部分を3366なりに変更します。
    また、[mysqld]と[mysql]のセクションに
    default-character-set=utf8
    を追加します。

    なんかスクリプトを流します。
    /usr/local/Calpont/bin/install-infinidb.sh

    InfiniDB用のmysqlクライアントを用意します。
    vi /usr/local/bin/idbmysql
    ------------------------------
    #!/bin/bash
    /usr/local/Calpont/mysql/bin/mysql --defaults-file=/usr/local/Calpont/
    mysql/my.cnf $*
    ------------------------------
    chmod 755 /usr/local/bin/idbmysql

    これで完了です。
    起動終了は、
    /etc/init.d/infinidb start
    /etc/init.d/infinidb stop
    になります。

    データベースの作成は通常のmysqlと変わりません。
    idbmysql -u root
    create database ttt;
    use ttt;

    テーブルもストレージエンジンにInfiniDBと指定することで作成できます。
    ただしindexをつけることができませんし、PKを含めNOT NULLなどの制約も利用できません。
    indexは実質不要でよいようなのですが、制約がかけられないのはちょっと面倒かもしれません。

    とりあえず性能を比較してみました。
    同じマシンで通常のmysql(InnoDB)とInfiniDBの両方を動かして
    以下のようなテーブルを用意します。
    TABLE名(tttt)
    id:int InnoDBではPKにします。
    code:varchar(16) InnoDBではindexを張ります。
    amount:int
    val:varchar(255)
    このテーブルに40万件ほどデータを入れておきます。

    それぞれに対して同じsqlを発行した結果です。
    (1)select count(*) from tttt;
     InnoDB:4.78 sec
     InfiniDB:0.73 sec

    (2)select sum(amount) from tttt;
     InnoDB:3.06 sec
     InfiniDB:0.38 sec

    (3)select code,sum(amount) from tttt group by code;
     InnoDB:6.72 sec
     InfiniDB:1.07 sec

    (4)select count(*) from tttt where code='AAAA';
     InnoDB:0.29 sec
     InfiniDB:0.47 sec

    (5)select * from tttt where code='AAAA' limit 1;
     InnoDB:0.00 sec
     InfiniDB:6.91 sec

    (6)select count(*) from tttt where val='test';
     InnoDB:2.73 sec
     InfiniDB:0.43 sec

    (7)select count(*) from tttt where val like '%es%';
     InnoDB:4.08 sec
     InfiniDB:0.48 sec

    確かにselectは、速い感じで確かにデータウェアハウスとかに適していそうな感じです。
    そのうち使ってみてもよいかもと思ってみたりしてみました。

    2010-05-20

    rails2.3.5でマルチプルinsertをする

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    mysqlのinsertのパフォーマンスをあげる方法として、マルチプルinsertを使うという方法があります。

    以下のようなVALUESをいっぱい書いた感じのSQLです。
    INSERT INTO <表名>
    [ <列名> [ , <列名> ... ] ]
    VALUES ( <値> [ , <値> ... ] ) ,
    VALUES ( <値> [ , <値> ... ] ) ,
    ・・・


    railsでは通常、普通のinsertが発行されてマルチプルinsertは使えません。

    しかし、
    ActiveRecord::Extensions
    を使えばできちゃいます。

    インストールは、
    gem install ar-extensions
    でOK。

    そしてenvironment.rbに
    config.gem 'ar-extensions'
    を追加します。

    そうすれば、importというメソッドが利用できるようになります。
    使い方は、以下のような感じです。
    columns = [ :author, :title ]
    values = [ [ 'araki', 'jojo' ],[ 'oda', 'onep' ] ]
    Book.import columns, values
    

    ActiveRecord::Extensions
    はマルチプルinsertだけでなく他にもいろいろ拡張されています。
    詳しくは以下のサイトが参考になります。
    http://d.hatena.ne.jp/yoshitetsu/20080129/1201610369
    ちなみにrails3では、ActiveRecord::Extensions利用できなそうな気配なのですが、importだけならば
    activerecord-import
    というので、できる感じです。

    activerecord-importは以下をご覧ください。
    http://github.com/zdennis/activerecord-import/

    ちなみに、このマルチプルinsertを使ってみた結果です。
    500件まとめてinsertしてみました。
    処理の前半で余計な前処理を結構しているので単純にinsert性能だけではないのですが、ご参考までに。

    仕様前
     件数 約3500件  Completed in 198245ms (DB: 10444)
     件数 約10000件 Completed in 492626ms (DB: 21144)
    使用後
     件数 約3500件  Completed in 169225ms (DB: 8538)
     件数 約10000件 Completed in 415683ms (DB: 16482)

    2010-05-19

    railsのmigrateでmysqlのbigintを使う

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    railsのmigrateでintegerを指定した場合は、mysqlではint型になっています。

    たまにbigintが使いたくなるケースがあります。
    そんな時は、
    :limit=>8
    をつけましょう。

    他のintシリーズを使いたい時は、
    http://ariejan.net/2009/08/20/once-and-for-all-rails-migrations-integer-limit-option/
    が参考になります。

    2010-05-13

    Googleドキュメントにあるドキュメントをランダムで取得してメールをする

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Googleドキュメントにいろいろメモを残しているのに全然見返すことをしていないない・・・
    そんな私のためにGoogle App EngineでGoogleドキュメントの内容をランダムで取得してメール送信するものを作ってみました。

    機能としては、
    ・文章のみをメール送信します。スプレッドシートなどは送信しません。
    ・取得対象はランダムです。
    ・文章を送信対象外にするリストを持ち、リストに追加したドキュメントは送信しません。
    ・oAuthを利用します
    てな感じです。

    エラー処理が少々大雑把なため
    ドキュメントが一つもなかったり、すごく大量にあった場合にどうなるかはわかりません。

    Djangoのアプリケーションになっています。
    http://docs.google.com/leaf?id=0BydytAINVs9VM2E5NWRlMGItNWM1Yy00OTZhLWI5MTctYjQ0MDliNWJhMjI0&hl=ja
    にアプリ部分だけzipしたものを置いてみましたので、もしご興味があればご利用ください。
    zipを解凍してできたディレクトリをDjangoプロジェクトのルートに配置して利用できるように設定します。
    ディレクトリ内のsettings.pyは編集する必要があります。

    実行には、gdataが必要です。
    以下から取得できます。
    http://code.google.com/p/gdata-python-client/

    Google App Engine patchも必要な気がします。
    こちらで利用しているモジュールも使っているような気がします。
    以下から取得できます。
    http://code.google.com/p/app-engine-patch

    app.yamlには
    - url: /gdoc_sender/.*
      script: common/appenginepatch/main.py
      login: admin
    
    みたいなエントリを追加する必要があります。

    あと、queue.yamlを以下のような感じで。
    queue:
    - name: default
      rate: 5/m
    
    - name: gdoc-sender
      rate: 5/m
    

    そして、cron.yamlを以下のような感じで。
    cron:
    - description: daily mail send
      url: /gdoc_sender/set_queue/
      schedule: every day of month 09:00
      timezone: Asia/Tokyo
    

    こんなメモを残していたのか・・・
    と毎日一つは残したメモを見返すようになりましたとさ。

    2010-05-12

    Bloggerでソースコードをきれいに表示する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    ソースコードをよく貼り付けているのですが、他の方のサイトでソースコードがきれいになっていることがよくあるので真似っこしたくなったのです。

    Bloggerで利用するには大きく2つあるようです。
    ・Syntax Highlighter
    以下が参考になります。
    http://u3q.blogspot.com/2010/01/bloggercom-syntax-highlighter-21-widget.html
    http://www.kuribo.info/2008/06/blogger-syntax-highlighter.html
    ・google-code-prettify
    以下が参考になります。
    http://www.kuribo.info/2008/04/code-prettify.html

    この2つを比較してみると
    Syntax Highlighterの方がこっていて
    google-code-prettifyの方はシンプルという感じです。
    というわけで
    Syntax Highlighter
    の導入を目指します。

    Syntax Highlighter
    の参考サイトを見るとウィジェットをさくっと導入できそうなのですが、私の環境ではなぜかダウンロードが始まってしまいうまく導入ができませんでした。
    原因はよくわからないのですが、利用しているテンプレートとかがいけないのかもしれないです。

    というわけで違う方法を探したところ以下のサイトの方法でうまくできました。
    http://www.craftyfella.com/2010/01/syntax-highlighting-with-blogger-engine.html
    英語のページですが、簡単に言ってしまうと、このページに書いてあるコードをテンプレートの直接編集で</head>の直前に入れるだけです。
    後は、以下のページの使い方で使えばよいだけです。
    http://u3q.blogspot.com/2010/01/bloggercom-syntax-highlighter-21-widget.html

    こんな感じになります。

    public class HelloWorld {
    public static void main(String[] args) {
    System.out.println("Hello World!");
    }
    }

    2010-05-09

    Google App Engineのタスクキューのメモ

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Google App Engineのタスクキューを利用したときのメモです。
    Pythonさんの場合です。

    defaultのキューではなくて、独自名称のキューを用意して利用する方法は、以下のリンク先を参考になります。
    http://mitsukuni.org/blog/2010/01/07/appengineでqueueを分ける/
    ちなみに独自で定義したキュー名にはアンダーバー(_)とかは使えません。
    使えるのは英数字とハイフン(-)だけっぽいです。
    使えない名前で定義してもエラーで教えてくれますけどね。

    あと、ローカルの開発環境でテストするには一度アプリケーションでadminユーザとしてログインしておかないと403エラーになってキューのテストができません。
    テスト環境でユーザログインの際に
    Sign in as Administrator
    にチェックを入れ忘れて、しばらく悩んでみました。
    app.yamlでキューのurlをadmin指定でなくせばダイジョブなのかもしれませんが。

    ちなみにcronの設定もadminユーザでログインしていないとダメでした。

    2010-05-07

    jQueryを使ってテーブルに行を追加したり削除したり

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    jQueryを使ってテーブルに行を追加したり削除したりしてみました。
    行の追加は、ヘッダー行の次に追加されるようにして、削除は各行に削除リンクが用意する感じです。

    以下のような感じです。
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <HTML lang="ja">
    <head>
    <META http-equiv="Content-Script-Type" content="text/javascript">
    <META http-equiv="Content-Style-Type" content="text/css">
    <meta http-equiv="Content-Type" content="text/html;charset=shift_jis">
    
    <title>test</title>
    <script src="jquery.js" type="text/javascript"></script>
    <script type="text/javascript">
    $(function(){
    $(".addadd").click(function(){
    var row_data = "<tr><td>ccc</td><td>" +  Math.floor( Math.random() * 100 )
    row_data = row_data + '</td><td><a href="#" class="deldel">削除</a></td></tr>'
    $("#tabtab tr:first").after(row_data);
    return false;
    });
    $(".deldel").live('click',function(event) { 
    $(this).parent().parent().remove();
    return false;
    });
    });
    </script>
    </head>
    <body>
    <a href="#" class="addadd">行を追加</a>
    <table border=1 id="tabtab">
    <tr><th>d1</th><th>d2</th><th></th></tr>
    <tr><td>aaa</td><td>bbb</td><td><a href="#" class="deldel">削除</a></td></tr>
    <tr><td>xxx</td><td>yyy</td><td><a href="#" class="deldel">削除</a></td></tr>
    </table>
    </body>
    </html>
    

    最近jqueryに関する本も増えてきましたね。


    2010-05-04

    googleドキュメントで作成した文章をAPIを利用してテキストで取得する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    googleドキュメントで作成した文章をGoogle App Engineで取り出したくなりました。
    Google App Engineで簡単に利用したいのでtext形式でダウンロードがしかくなったのです。

    以下のような感じで取れました。
    Djangoでの例です。
    とりあえず前件取得してランダムで取得してみます。
    # -*- coding: utf-8 -*-
    import random
    from django.http import HttpResponseRedirect
    from django.utils.translation import ugettext as _
    from ragendja.template import render_to_response
    from django.conf import settings
    import gdata.gauth
    import gdata.docs.client
    import gdata.docs.data
    
    APP_NAME = 'googleDocumentTextGetTest'
    def index(request):
      payload = dict()
      client = gdata.docs.client.DocsClient(source=APP_NAME)
      client.ssl = True
      client.ClientLogin('googleアカウントのメールアドレス', 'そのパスワード', client.source)
      payload['feed'] = client.get_everything()
      feed_len = len(payload['feed'])
      while True:
        get_doc = random.randint(0, feed_len-1)
        payload['selection'] = payload['feed'][get_doc]
        #取れたものがスプレッドシートとかだったらもう一回取り直す
        doc_type = payload['selection'].GetDocumentType()
        if doc_type == "document":
          break
      doc_uri = '/feeds/download/documents/Export?docID=' + payload['selection'].resource_id.text + '&exportFormat=txt'
      payload['content'] = client.get_file_content(doc_uri)
      return render_to_response(request, 'index.html',payload)
    


    参考までにテンプレートは以下のような感じです。
    <!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html
    xmlns="http://www.w3.org/1999/xhtml"
    dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
    xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
    lang="{% firstof LANGUAGE_CODE 'en' %}">
    <head>
    <title>test</title>
    </head>
    <body>
    {{ selection.title.text }}<br>
    <pre>
    {{ content }}
    </pre>
    <ul>
    {% for entry in feed.entry %}
    <li>{{ entry.title.text }}</li>
    {% endfor %}
    </ul>
    <body>
    <html>  
    


    本当だったら、全件取得でなく以下のような感じで
    /feeds/default/private/full/-/document
    documentファイルだけを取得したかったのですが、なぜかできませんでした。

    2010-05-02

    GAEでgoogleさんにOAuth

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Google App EngineでgoogleさんにOAuthしてみました。
    Djangoを使ったpythonで実験しています。

    まずは準備としてGoogleさんにサイトを登録して
    Consumer Key

    Consumer Secret
    を手に入れる必要があります。

    https://www.google.com/accounts/ManageDomains
    で利用ドメインを登録します。すると
    Manage registration
    に登録したドメインが出るのでクリックします。
    最初に登録したドメインのページにメタタグを埋め込んでサイトの確認を実行します。
    すると
    Target URL path prefix:
    を入れる欄が出てくるようになるので
    とりあえず
    サイトでOAuthを利用するパスを入れてセーブします。
    例:
     http://xxxx.xxxx.xxxx/oauth_test/index.html
     とかでOAuthを使ったもろもろをoauth_test配下に入れて置くならば、
     http://xxxx.xxxx.xxxx/oauth_test
     を登録します。
    (実際は、どんなものを入れるのがよいのかいまいちよく分かっていません)

    これで
    Consumer Key

    Consumer Secret
    が発行されるのでメモしておきましょう。

    今回OAuth関連の処理をするものとしてgdataを利用します。
    http://code.google.com/p/gdata-python-client/
    gdataは、OAuth用というよりもGoogleカレンダーとかドキュメントとかのAPIを扱う便利クライアントです。
    OAuthしたらなんらかのgoogleのAPIを利用するのでこれを利用します。
    取得したら、
    Djangoプロジェクトディレクトリ直下に
    atom
    gdata
    をコピーします。

    今回、OAuthを試すアプリとして
    oauth_test
    を作ります。
    これはgoogleドキュメントに登録してあるデータ一覧を取得するものにしてみます。
    なのでsettings.pyに使えるように設定しておきます。
    またoauth_testでは認証がかかるようにapp.yamlに以下を追加します。

    - url: /oauth_test/.*
    script: common/appenginepatch/main.py
    login: required

    なので今回用意したものは以下のような感じです
    Djangoルート
    |-atom
    |-gdata
    |-oauth_test
    |-template
    | |-index.html
    |-settings.py
    |-urls.py
    |-urlsauto.py
    |-views.py

    oauth_test配下のものはざっと以下のような感じです。

    settigns.py

    from ragendja.settings_post import settings
    settings.CONSUMER_KEY = '取得したConsumer Keyを入れます'
    settings.CONSUMER_SECRET = '取得したConsumer Secretを入れます'


    urlsauto.py

    # -*- coding: utf-8 -*-
    from django.conf.urls.defaults import *
    rootpatterns = patterns('',
    (r'^oauth_test/', include('oauth_test.urls')),)


    urls.py

    # -*- coding: utf-8 -*-
    from django.conf.urls.defaults import *
    urlpatterns = patterns('oauth_test.views',
    (r'^$', 'index'),
    (r'^oauth_set/$', 'oauth_set'),
    (r'^oauth_callback/$', 'oauth_callback'),
    (r'^oauth_revork/$', 'oauth_revork'),
    )


    view.py

    # -*- coding: utf-8 -*-
    from django.http import HttpResponseRedirect
    from django.utils.translation import ugettext as _
    from ragendja.template import render_to_response
    from django.conf import settings
    from google.appengine.api import users

    import gdata.gauth
    import gdata.docs.client
    import gdata.docs.data

    APP_NAME = 'oauthMyTest'
    def index(request):
    payload = dict()
    login = users.get_current_user()
    #すでに登録済みかどうかを確認します
    #gdata.gauth.Ae*を利用することでGoogle App Engineのデータストアに
    #取得したOAuthのトークンとシークレットをオブジェクトして格納して出し入れできます。
    #memcacheのようにキーとtokenがセットになっています。
    #ここではログインユーザのuser_idをキーにしています。
    token = gdata.gauth.AeLoad(login.user_id())
    if token == None:
    payload['have_token'] = False
    else:
    payload['have_token'] = True
    #ドキュメント一覧を取得します
    #client.ssl = Trueを必ずつけましょう
    #付け忘れるとInvalid Tokenとか言われて悩みます
    client = gdata.docs.client.DocsClient(source=APP_NAME)
    client.ssl = True
    client.auth_token = gdata.gauth.AeLoad(login.user_id())
    payload['feed'] = client.get_doclist()
    return render_to_response(request, 'oauth_test/index.html',payload)

    def oauth_set(request):
    #googleにリダイレクト処理をします
    SCOPES = ['https://docs.google.com/feeds/']
    callback_url = 'http://%s/oauth_test/oauth_callback/' % request.get_host()
    client = gdata.docs.client.DocsClient(source=APP_NAME)
    request_token = client.GetOAuthToken(SCOPES, callback_url, settings.CONSUMER_KEY, consumer_secret=settings.CONSUMER_SECRET)
    login = users.get_current_user()
    #callbackしてきたときに利用できるように一時的にtokenを格納します。
    gdata.gauth.AeSave(request_token, "tmp_" + login.user_id())
    return HttpResponseRedirect(request_token.generate_authorization_url())

    def oauth_callback(request):
    #アクセス用のトークンとトークンシークレットを格納します
    login = users.get_current_user()
    #一時的に格納したtokenを取り出し削除しておきます。
    saved_request_token = gdata.gauth.AeLoad("tmp_" + login.user_id())
    gdata.gauth.AeDelete("tmp_" + login.user_id())
    request_token = gdata.gauth.AuthorizeRequestToken(saved_request_token, request.build_absolute_uri())
    client = gdata.docs.client.DocsClient(source=APP_NAME)
    try:
    #ここでアクセストークンを取得して格納
    access_token = client.GetAccessToken(request_token)
    gdata.gauth.AeSave(access_token, login.user_id())
    except:
    logging.info('cant get access token')
    return HttpResponseRedirect('/oauth_test/')

    def oauth_revork(request):
    #取得したtokenを破棄します
    login = users.get_current_user()
    gdata.gauth.AeDelete(login.user_id())
    return HttpResponseRedirect('/oauth_test/')


    template/index.html

    <!DOCTYPE html
    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml"
    dir="{% if LANGUAGE_BIDI %}rtl{% else %}ltr{% endif %}"
    xml:lang="{% firstof LANGUAGE_CODE 'en' %}"
    lang="{% firstof LANGUAGE_CODE 'en' %}">
    <head>
    <title>oauth_test</title>
    </head>
    <body>
    {% if have_token %}
    <a href="/oauth_test/oauth_set/">登録する</a>
    {% else %}
    <ul>
    {% for entry in feed.entry %}
    <li>{{ entry.title.text }}</li>
    {% endfor %}
    </ul>
    <hr>
    <a href="/oauth_test/oauth_revork/">登録を解除する</a>
    {% endif %}
    </body>
    </html>


    こんな感じです。
    TwitterのOAuthと比べるとちょっとめんどっちい感じです。

    2010-04-29

    携帯電話用USB充電&データ転送ケーブル/ストラップタイプ

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    これオススメです。

    amazonさんの評判は悪くないのですが、結構普通に使えていました。
    携帯とPCがどこでもガシガシ接続できて、携帯をUSBメモリとしても利用できていい感じでした。


    しかし、最近あんまり利用してなくて久しぶりに使おうと思ったら、
    USBminiと携帯を接続するコネクタがなくなっていました・・・

    全然気づかなかったです・・・
    なのでもうこれを使えません・・・
    もう一度買おうかなぁ・・・
    本当ならば変換コネクタだけ欲しいのだけど・・・

    2010-04-27

    wheneverで環境変数を指定する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    rubyでcron設定を記述できるwheneverなのですが、cron実行時に特別に環境変数を指定したいときなどは、以下のような感じで指定することもできます。

    config/schedule.rb
    に以下のような感じを追加します。

    env :TNS_ADMIN , "/usr/local/oracle/network/admin"
    env :NLS_LANG , "Japanese_Japan.UTF8"


    こうしておいて
    whenever
    コマンドを実行すると

    TNS_ADMIN=/usr/local/oracle/network/admin
    NLS_LANG=Japanese_Japan.UTF8

    が追加されます。

    ついでにcronの出力を
    >> /dev/null 2>&1
    としたいときは、
    config/schedule.rb

    set :output, nil

    を追加すればよいです。

    wheneverについては、以下にもちょっと書いています。
    wheneverでcron処理情報を管理

    2010-04-26

    google app engine patchでアプリ内に独自設定値を定義して利用する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    google app engine patchでアプリ内で独自の設定を定義して利用する方法です

    通常
    root
    |-myapp
    |-settings.py ← ここに設定値とかを書くわけですが、
    ここだとグローバルな設定値な感じなので
    myapp内だけで利用するような設定値を定義したい場合です。

    myapp内にもsettings.pyを用意します。
    root
    |-myapp
    | |-settings.py
    |-settings.py

    この自アプリ内のsettings.pyを以下のように書きます。

    from ragendja.settings_post import settings
    settings.MY_TEST = 'test test'

    で使う時には、以下のような感じです。

    from django.conf import settings

    def index(request):
    mytest = settings.MY_TEST

    2010-04-19

    SOBARCOでTwitterに投稿できるようにしてみました

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    SOBARCOでTwitterに投稿できるようにしてみました。

    今までは、SOBARCOのRSSをFriendFeedに読み込ませてTwitterに投稿していたのですが、表示される内容がタイトルだけのようでちょっと物足りなかったのと、そのうち試そう試そうと思っていたのをやって試してみたという感じです。

    Twitterに自分の呼んだ本の感想などを本のタイトルと一緒に投稿したいときなどもSOBARCOを利用していただけたらと思います。

    あと、Amazonアフィリエイトのキーを入れられるようにしたいと思っていたりするのですが、単純にアフィリエイトのキーの部分だけ置換すればよいのかどうかがいまいちわからずです。

    2010-04-18

    Google App EngineからTwitterにつぶやく

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Google App EngineからTwitterにつぶやく方法です。

    まず用意するのは、
    TwitterのOauthサイトに飛ぶための機能
    TwitterのOauthからCallbackされるところ
    が必要です。

    これがつぶやくための情報が取得できたことになるので
    これではじめてつぶやけます。

    まずTwitterのAPIを利用するための登録をTwitterに行います。
    http://www.msng.info/archives/2010/01/twitter_api_oauth_with_php.php
    がとても参考になります。

    そしてGoogle App EngineからTwitterのAPIを利用するには、
    AppEngine-OAuth-Library
    が大変便利です。
    使い方は、
    http://blog.mudaimemo.com/2010/02/google-app-engine-twitter-oauth.html
    が大変参考になります。

    ざっくり使うならば以下のような感じになります。
    # -*- coding: utf_8 -*-
    
    import os
    import sys
    import logging
    
    from google.appengine.ext.webapp import template
    from google.appengine.ext import webapp
    from google.appengine.api import urlfetch
    from django.utils import simplejson as json
    import traceback
    import urllib
    #AppEngine-OAuth-Libraryを読み込みます。
    import oauth
    
    import wsgiref.handlers
    
    #登録した値を使います
    CONSUMER_KEY = 'アプリのConsumer key'
    CONSUMER_SECRET = 'アプリのConsumer secret'
    
    class Top(webapp.RequestHandler):
      def get(self):
        template_values = {}
        path = os.path.join(os.path.dirname(__file__), 'top.html')
        self.response.out.write(template.render(path, template_values))
    
    class TwitSignin(webapp.RequestHandler):
      def get(self):
            callback_url = '%s/twitter/callback' % (request.host_url)
            client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,callback_url)
            self.redirect(client.get_authorization_url())
    
    class TwitCallback(webapp.RequestHandler):
      def get(self):
        #つぶやくために必要なのは以下の二つではありません
        token = request.get('oauth_token')
        verifier = request.get('oauth_verifier')
        client = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET,None)
        #以下の部分で肝心な情報を取得します
        user_info = client.get_user_info(token, verifier)
        #この下で取得する2つの情報がつぶやくために必要になります
        oauth_token  = user_info['token']
        oauth_secret = user_info['secret']
    
        #重要な情報がとれたところでついでにつぶやきサンプルです。
        msg = "oauthテスト なう"
        additional_params = {'status': msg}
        try:
            response = client.make_request('http://twitter.com/statuses/update.json',
                                           token=oauth_token,
                                           secret=oauth_secret,
                                           additional_params=additional_params,
                                           protected=True,
                                           method='POST')
            data = json.loads(response.content)
            if data.has_key('error'):
                logging.error(data['error'])
        except Exception, e:
            logging.error(traceback.format_exc())
            
        self.redirect("/")
    
    
    def main():
      application = webapp.WSGIApplication([
                                            ('/', Top),
                                            ('/twitter/signin', TwitSignin),
                                            ('/twitter/callback', TwitCallback),
                                            ],
                                           debug=True)
      wsgiref.handlers.CGIHandler().run(application)
    
    if __name__ == "__main__":
      main()
    

    ちなみにtop.htmlは
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
        "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>test</title>
    </head>
    <body>
    <a href="/twitter/signin">auth twitter</a>
    </body>
    </html>
    

    2010-04-15

    railsでOracleに接続できるようにする

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    railsでoracleに接続できるようにするための手順です。

    環境はCentOSでrubyは導入済みなのが前提です。

    (1)oracleクライアントインストール手順
    http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/linuxsoft.html
    から
    以下をダウンロード(バージョンはお好きなものを)
    oracle-instantclient-basic-10.2.0.3-1.i386.rpm
    oracle-instantclient-sqlplus-10.2.0.3-1.i386.rpm
    oracle-instantclient-devel-10.2.0.3-1.i386.rpm

    (2)oracleクライアントインストール
    su -
    rpm -ivh oracle-instantclient*

    (3)接続設定
    vi /usr/local/oracle/network/admin/tnsnames.ora
    必要な設定を記述する

    (4)環境変数の設定
    vi /etc/profile.d/oracle.sh
    -------------------------
    export TNS_ADMIN=/usr/local/oracle/network/admin
    export NLS_LANG=Japanese_Japan.UTF8
    export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client
    export PATH=${ORACLE_HOME}/bin:${PATH}
    export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${LD_LIBRARY_PATH}
    -------------------------
    chmod 755 /etc/profile.d/oracle.sh

    (5)接続テスト
    例えば以下のような感じ
    sqlplus scott/tiger@test

    (6)Ruby-OCI8インストール
    gem install ruby-oci8

    (7)OracleAdapterインストール
    gem install activerecord-oracle_enhanced-adapter

    (8)rubyでの接続確認
    例えば以下のような感じ
    irb
    irb> require 'oci8'
    => true
    irb> con = OCI8.new("scott","tiger","test")
    => #
    irb> con.exec('select * from DUAL') do |r| puts r.join(', '); end
    X
    => 1

    2010-04-14

    Google App Engineで短縮URLのAPIを利用する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    最近、よく見る短縮URLをGoogle App Engineでも利用してみます。
    bit.lyは、APIを利用できるのでbit.lyを使うことにします。

    利用のためには、以下でアカウント登録が必要ですが無料ですし必要なのはメールアドレスだけです。
    http://bit.ly/account/register
    登録が済んだら以下でApiKeyを取得します。
    http://bit.ly/account/your_api_key

    ここまで出来たら準備OK。

    以下のような関数を作って呼び出せば、短縮urlを利用できます。
    # -*- coding: utf_8 -*-
    
    from google.appengine.api import urlfetch
    import urllib
    
    def make_short_url(url):
        bitly_account = "bit.lyに登録したアカウント"
        bitly_key     = "bit.lyから発行されたAPIキー"
        bitly = "http://api.bit.ly/v3/shorten"
        bitly = bitly + "?login=" + bitly_account + "&apiKey=" + bitly_key
        bitly = bitly + "&format=txt"
        bitly = bitly + "&longUrl=" + urllib.quote_plus(url)
        result = urlfetch.fetch(bitly)
        if result.status_code != 200:
            return None
        return result.content[:-1]
    

    2010-04-10

    踏み台昇降

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    この本を読んでみました。


    この本では、トレッドミル(ルームランナー)をオススメしていました。
    以下のような折りたためる家庭用のものを特にオススメしていました。

    というのも、
    ・ながら運動ができる
    ・いつでもできる
    ・周りに気を使わなくてよい
    ・すぐにやめて他の行動に移れる
    ・運動量が数値化して示される
    ・継続しやすい
    ・物質の調達が用意(水とか)
    ・つかまりながら歩ける/走れる
    というメリットがあるからだそうです。
    特にながら運動の点で
    テレビやDVDや読書、コーヒーを飲みながらだけでなく
    以下のようなパイプラックを近くにおいて台にすることでパソコンなどの操作をしながらもOKとのことでした。


    なるほど、これはキニナル!
    と思ったわけです。
    でちょっと調べてみたところ、いくら折りたためると言ってもせまい我が家にはでかすぎる・・・
    と思ったわけです。

    場所がないなら以下のようなステッパーでもいいじゃないか?と思ったわけです。


    さらによく考えたら、足踏みということで踏み台昇降でいいんじゃねぇ。と思ったりしたのです。
    以下のようなステキな台もあるわけですが、新聞紙とかをガムテープでぐるぐる巻きにして台を作ってもよいというお手軽さです。


    そして踏み台昇降で調べたところ以下のサイトを見つけました。
    http://beauty.s35.xrea.com/diet/
    こちらではポイントとしては、台にあがる最初にあげる足をを定期的に左右いれかえるとありました。
    そのため、台の上で一歩足踏みして台の上で3歩、下で2歩というのが良い感じのようです。

    というわけで、トレッドミルのメリットと比較をしてみます。
    ○ながら運動ができる
     ただし水を飲みながらは上下移動なのでちょっと大変
    ○いつでもできる
    ○周りに気を使わなくてよい
    ○すぐにやめて他の行動に移れる
    ×運動量が数値化して示される
    ○継続しやすい
    ○物質の調達が用意(水とか)
    ○つかまりながら歩ける/走れる
     つかまれるとこの近くでやればという条件つき

    ほとんどトレッドミルのメリットと同様のメリットが踏み台昇降にはあることがわかりました。
    数値化に関しても歩数計を使えばバッチリ!


    ちょっと踏み台昇降生活がキニナルこのごろになってみました。

    2010-04-06

    はてなモノリス

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    はてなさんで
    はてなモノリス
    というサービスがはじまったようです。


    はてなモノリスは,iPhone 3GSやAndroid端末を使って,身の回りにある「モノ」のバーコードをスキャンし,その情報をWeb上に共有するサービス。

    だそうです。

    どこかで聞いたことがあるようなコンセプト。
    SOBARCO
    も同じ(つもり)コンセプトなのです。

    機能的には、もちろん
    はてなモノリス
    さんが上です!

    私もAndroidやiPhoneアプリも作ってみたかった・・・
    ですが実機がなくてモチベーションがあがらず。

    twitter連携などは、そのうちやってみたいなぁとか思ったりもしているので
    もし
    iアプリで
    はてなモノリス
    みたいなことをやってみたいなぁと思う方がいましたら
    SOBARCO
    をお試しください。

    2010-03-31

    wheneverでcron処理情報を管理

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    rubyでcron処理を記述し、実際にcrontabに記載を行うwheneverというものがあることを知りました。

    インストール方や利用方法は、
    http://tobysoft.net/wiki/index.php?Ruby%2FRuby%20on%20Rails%2Fcron%C5%AA%A4%CA%A4%B3%A4%C8%2Fwhenever
    を見ていただくのがよいです。

    RAILS_ROOT/config/schedule.rbに
    以下のように書いておけば
    every 2.days, :at => '4:30am' do
      command "/usr/bin/my_great_command" 
    end
    
    crontabに
    30 4 1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31 * * /usr/bin/my_great_command
    
    と書いてくれるわけです。
    RAILS_ROOT配下にcronに関する情報も記載できるのがいい感じだと思います。

    こんな感じで毎月5日に実行する処理みたいなことを書きたいと思ったのですが、
    at
    にどういうふうに書けばよいのかわからなかったのですが、
    every 1.months, :at => "jan 5th 22:00"
    
    ととりあえず月まで入れてしまって日付をしていすることで指定できました。
    このように指定してもちゃんと毎月の設定になりました。

    atの部分の記載は、
    Chronic
    というものでパースをしているようです。

    Chronicについては
    http://chronic.rubyforge.org/
    をみてください。
    こちらのような記述がatの部分にできいるようです。
    いろいろな形で指定できるようです。

    2010-03-25

    MySQLでslow_query_logを有効にするようにmy.cnfに書く

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    MySQLで時間がかかるSQLをログ出力するためには
    slow_query_logをONにする必要があります。
    でも
    my.cnfには
    slow_query_log = ON
    ではなく
    slow_query_log = 1
    とかかなくてはいけないのでした。

    参考にさせていただいたのは、
    http://twitter.com/hirose31/status/2948103962
    です。

    2010-03-15

    OracleさんとPassenger

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Oracleに対して接続するRailsアプリを作り、Passengerで動かしているのですが、
    1日2日ほったらかして久しぶりに接続すると接続タイムエラーになり接続できない感じだったりしました。

    ちなみにoracleへの接続は
    oracleのinstantclient

    oracle_enhanced
    を利用しています。

    ほんとに接続できないかどうか確認するために
    sqlplus

    script/consoleでモデルに対してfindを実行
    したりするとなんら問題なしだったりします。

    そしておかしいなぁと思いつつ
    apacheを再起動すると動くのが続きました。

    RAILS_ROOTに以下のようなsqlnet.logが記録されていました。

    Fatal NI connect error 12170.

    VERSION INFORMATION:
    TNS for Linux: Version 10.2.0.3.0 - Production
    TCP/IP NT Protocol Adapter for Linux: Version 10.2.0.3.0 -
    Production
    Time: 15-MAR-2010 09:23:21
    Tracing not turned on.
    Tns error struct:
    ns main err code: 12535
    TNS-12535: Message 12535 not found; No message file for product=
    network, facility=TNS
    ns secondary err code: 12560
    nt main err code: 505
    TNS-00505: Message 505 not found; No message file for product=
    network, facility=TNS
    nt secondary err code: 110
    nt OS err code: 0


    最初は、たまたま負荷が高いときに接続していて本当に接続タイムアウトになったのかなと思っていたのでが、どうも環境変数がうまく反映されていないようでした。

    ちなみに接続には
    tnsnames.ora

    /usr/local/oracle/network/admin
    に記述して利用しています。
    なので
    config/database.yml
    は以下のような感じです。

    production:
    adapter: oracle_enhanced
    database: test
    username: test
    password: test


    なので環境変数を確実に反映されるために以下のようなシェルスクリプトを
    /usr/local/bin/ruby_with_env
    として用意しました。

    #!/bin/bash
    export TNS_ADMIN=/usr/local/oracle/network/admin
    export NLS_LANG=Japanese_Japan.UTF8
    export ORACLE_HOME=/usr/lib/oracle/10.2.0.3/client
    export PATH=${ORACLE_HOME}/bin:${PATH}
    export LD_LIBRARY_PATH=${ORACLE_HOME}/lib:${LD_LIBRARY_PATH}
    /usr/bin/ruby $*

    PATHは設定がなくてもよいと思いますが、なんとなく追加です。

    chmod 755 /usr/local/bin/ruby_with_env
    としておいて

    Passengerの設定のRailsRubyを以下のようにします。
    RailsRuby /usr/local/bin/ruby_with_env

    参考にしたのは、
    http://blog.rayapps.com/2008/05/21/using-mod_rails-with-rails-applications-on-oracle/
    です。

    これでいけるようになった気がします。

    iアプリで加速度センサを使ってみようと思ったけど対応していなかったのでした

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    iアプリで加速度センサで遊んでみようと思ってみたわけです。

    加速度センサは
    com.docomostar.device.location.AccelerationSensor
    を利用すればできると書いてありました。

    エミュレータではなんとなく値が取れるものができたので、実機で試そうとしたら
    エラーが発生しました
    といわれて終了。

    試したのはSH-04Aだったのですが、
    http://www.nttdocomo.co.jp/service/imode/make/content/iappli/technical_data/star/

    iアプリコンテンツ開発ガイド for Star-1.x 各機種オプションAPI・拡張API実装状況
    を確認してみると確かに対応していませんでした。
    というか、対応している機種がほとんどないのです。

    画面を傾ければ横画面に切り替わったりするので、使えると思い込んでみました。

    ちなみに
    iアプリのADF設定で
    AppTrace

    on
    にすると実機で発生した例外が
    情報表示のトレース表示
    に記録されるようになります。

    iアプリって、もっといろんな制限をとりはずして開放していればiPhoneとかが入ってくる余地とかない感じになりえたような気がします。
    そしてもう今から開放してももう遅いのだろうなぁという気もします。

    2010-03-10

    ambienTecの太陽電池

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    おしゃれな太陽電池でキニナリます。
    これくらいオシャレならば普段別に充電が必要なわけではないですが、持ちたくなってみたりしました。

    rspecでflash.nowのテストを書く

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    rspecでflash.nowにメッセージがセットされていること確認するテストを書く方法です。
    通常のflashであれば
    flash[:warning].should == "わーにんぐー"
    のように書けばよいわけです。

    flash.nowの場合調べると
    flash.now[:warning].should == "わーにんぐー"
    と書けばよさげに見えたのですが、
    Rails2.3.5では
    response.flash[:warning].should == "わーにんぐー"
    と書かないとダメでした。

    理由はよくわかりません。

    2010-03-03

    railsで処理中メッセージを出して他の処理をできないようにする

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    なんかしらの処理を行っている際に他のボタンなどを押してもらいたくないことがあったりします。

    Railsには、2重クリック防止として
    submit_tag("実行",:disable_with => "処理中...")
    のような感じにすれば、そのボタンをdisableにして2重クリックは防止できます。
    ただ、あくまでも押したボタンだけが押せなくなるだけで、他のメニューなどは当然クリックなどができます。

    これを防止するためにjqueryのプラグインの
    jQuery BlockUI Plugin (v2)
    を使わせていただくことにしました。

    使い型的には、以下のような感じです。
    まずはヘッダーぐらいに以下のような感じで書いておきます。
    <%= javascript_include_tag 'jquery' %>
    <%= javascript_include_tag 'jquery.blockUI' %>
    <script type="text/javascript">
     <!--
      $(function($) {
       $('.exec_do').click(function() {
        $.blockUI({ message:'<h1>実行中...</h1>' });
       });
      });
     // -->
    </script>
    

    そしてsubmitの部分を
    submit_tag("実行",:class => "exec_do")
    とすればよいです。

    2010-03-02

    cache_fuでキャッシュをすべてクリア

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    RailsのActiveRecordの結果をmemcacheにキャッシュしてくれるcache_fuですが、キャッシュ済みのものを削除したいことがあります。
    消したいものが明確であれば、expire_cacheを使えばよさげだと思うのですが、一括更新などをしてほとんど更新したから、いっそ全部消してしまいたいということもあります。
    そんなときは、
    CACHE.flush_all
    とすればOKです。
    これだとmemcacheでキャッシュされているものをすべて消してしまうので、場合によっては消しすぎになるかもしれませんが。

    2010-02-21

    ActiveRecordのパフォーマンスチューニングをしてみた

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    RailsのActiveRecordのパフォーマンスチューニングをざっくりとした感じで試しました。

    アプリケーションの内容は、csvファイルを受け取りそこのデータをデータベースに読み込ませるというもので、データのチェックとして4つぐらいマスターテーブルにデータが存在するかどうかのチェックを行うというものです。

    実行時間は、
    log/development.log
    に記録されるものを利用します。

    まず最初の状態。
    Completed in 328217ms (DB: 116445)

    マスターファイルにデータが存在するかどうかを
    find_by_xxx
    で行っていたのですが、これは遅いよみたいなことがあったので、これをすべて
    find
    に書き換えた結果。
    Completed in 308355ms (DB: 117323)

    さらにマスター検索部分をcache_fuを利用してmemcachedにキャッシュさせた時の結果。
    Completed in 262213ms (DB: 39203)

    マスター検索ぐらいの比較的類似データの検索がかかるようなものは、DBのキャッシュにひっかかり、memcachedを利用してもそんなに変わらないと思っていたのですが、結構かわるもんですね。

    ちなみに
    cache_fu
    を利用するために
    gem install system_timer --include-dependencies
    gem install memcache-client --include-dependencies
    ./script/plugin install git://github.com/defunkt/cache_fu.git
    をやって、
    マスター用のモデルに以下のようなコードを書きました。

    class Zip < ActiveRecord::Base
    acts_as_cached :ttl => 10.minutes

    def self.get_zip_cache(code)
    self.get_cache("zip_#{code}") do
    find(:first,:conditions => ["zipcode = ?",code])
    end
    end
    end

    こんなコードを書いた後に
    Zip.find(:first,:conditions => ["zipcode = ?",code])
    していた部分を
    Zip.get_zip_cache(code)
    と変更しています。

    2010-02-19

    CentOS5.4環境でexcelファイルをrubyで読み込む

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    rubyではSpreadsheetというのでExcelファイルを読み込めます。
    インストールは、
    sudo gem install spreadsheet
    でOKです。

    なのですが、CentOS5.4の環境で試したところ
    WINDOWS-932がUTF-8に変換できないよ!
    といわれてファイルを読み込むことができませんでした。
    ちなみにrubyのバージョンは1.8.7です。

    たしかに
    iconv -l
    と利用できる文字コードを見ると
    WINDOWS-932
    がありませんでした。

    なので、
    sudo vi /usr/local/lib/ruby/gems/1.8/gems/spreadsheet-0.6.4.1/lib/spreadsheet/excel/internals.rb
    で、以下のようにWINDOWS-932を指定している部分をCP932に変更したら読めるようになりました。

    # 932 => "WINDOWS-932", #(Japanese Shift-JIS)
    932 => "CP932", #(Japanese Shift-JIS)

    ちなみにrubyのインストールprefixを/usr/localにしている場合です。
    別に
    SHIFT-JIS
    とかでもよいのかもしれませんが、CP932にしてみました。

    2010-02-15

    ActiveScaffoldとjQueryのthickboxを組み合わせる

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    ActiveScaffoldとjQueryでモーダルダイアログを表示するthickboxを組み合わせてみました。

    郵便番号をzipsテーブルに格納してあり、郵便番号を検索するための画面をthickboxでモーダルダイアログとして表示します。
    そこで検索とかして最終的に親のwindowの方の郵便番号欄に値を入れる感じです。

    郵便番号欄のフォームのためのviewは以下のような感じです。
    jqueryやthickboxのjavascriptやstylesheetは取得してpublic配下に適切においてあるとします。
    ・・・略
      <%= javascript_include_tag 'jquery' %>
      <%= javascript_include_tag 'thickbox' %>
      <%= stylesheet_link_tag 'thickbox' %>
    ・・・略
     郵便番号:
     <%= text_field_tag("zip","", {:maxlength => "7"}) %>
     <%= link_to "検索",{:controller=>"zips",:action=>"index",:TB_iframe=>"true",:height=>"400",:width=>"600"},{:class=>"thickbox",:title=>"郵便番号検索"} %>
    ・・・略
    
    ActiveScaffoldを使っているとTB_iframeを指定してiframeで開かないとうまく開きませんでした。

    これから呼び出されるZipsControllerは以下のような感じです。
    一応、モーダル用のlayoutを別途用意しているものとしています。
    こちらのレイアウト上でjqueryは読み込んでいます。
    モーダル上で郵便番号をクリックすると親windowの郵便番号欄に渡されるようにします。
    class ZipsController < ApplicationController
      layout "modal"
    
      active_scaffold :zips do |config|
        config.label = "郵便番号検索"
        config.actions = [:list, :search]
        config.columns = [:code,:address]
        config.columns[:code].label = "郵便番号"
        config.columns[:address].label = "住所"
        config.list.sorting = [{:code => :ASC}]
        config.search.columns << [:code,:address]
      end
    end
    
    module ZipsHelper
      def code_column(record)
        link_to_function record.code,"$('#zip',window.parent.document).val('#{record.code}');
        self.parent.tb_remove();"
      end
    end
    
    ZipsHelperをこのコントローラーを書いたファイルと同じファイル内に書いています。
    ZipsHelperを普通にhelperとして用意してしまうとcodeを利用する部分すべて置き換わってしまいます。
    iframeで表示しているので親windowの値を利用するためにparentをちょいちょい書いてあります。

    最近は便利なものが本当にいろいろありますね。

    2010-02-07

    ActiveScaffoldでデータを保存する際にsessionに格納されている情報を利用する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Railsではマスタメンテナンス系のためにScaffoldがありますが、そんなScaffoldを素敵にしてくれるActiveScaffoldがお気に入りなのです。

    ActiveScaffoldのインストール方法や利用方法は検索すればすぐわかると思いますので割愛します。

    そんなActiveScaffoldで特定のカラムにsessionに格納されているデータを利用して格納する場合です。
    ある情報を誰が作成更新したかなどをsessionに格納しているlogin情報などを利用して更新する場合などを想定しています。

    仮に以下のようなtestsテーブルがあるとします。
    id
    data
    data2
    recorder
    create_at
    updated_at
    
    このrecorder部分にデータを作成または更新した人の情報を格納するものとします。
    更新した人の情報はsession[:login]に格納されているものとします。

    このtestsテーブルのメンテナンス画面をActiveScaffoldを利用する場合です。
    モデルは定義済みとしてcontrollerは、以下のようにすればOKです。
    class TestController < ApplicationController
      active_scaffold :tests do |config|
        config.label = "テストメンテナンス画面"
    
        config.columns = [:data,
                          :data2]
        config.columns[:data].label    = "登録必須データ"
        config.columns[:data].required = true
        config.columns[:data2].label         = "登録必須でないデータ"
        config.columns[:recorder].label  = "更新者"
        config.columns[:created_at].label    = "作成日時"
        config.columns[:updated_at].label    = "更新日時"
        config.columns[:data].search_sql = 'data'
    
        config.list.columns << :recorder
        config.list.sorting = [{:data => :ASC}]
    
        config.show.columns << [:recorder,
                                :created_at,
                                :updated_at]
    
        config.search.columns << :data
      end
    
      protected
      def before_create_save(record)
        record[:recorder] = session[:login]
      end
    
      def before_update_save(record)
        record[:recorder] = session[:login]
      end
    end
    

    ポイントはcontroller内に定義した
    before_create_save(record):新規登録用
    before_update_save(record):更新処理用
    を利用することです。

    最初は、何も考えずにModelの
    before_saveでsession情報を取ろうとしてしまったのですが、
    session情報は、Modelでは取れないわけなのでした。

    2010-02-05

    Windows環境で作成したShift-JISのタブ区切りファイルをUTF-8でlinux上のrubyで扱う

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    ファイル読み込みを行う際にcsvやtsvファイルを作ってもらって読み込むことが多々あると思います。
    そんなファイルはたいていShift-JISになっていて、さらに最初の行がカラムの説明行になっていることもよくあると思います。

    例えば、以下のようなファイルです。
    test.tsv

    日付 お名前 性別
    2010/2/5 お試しするぞう 男
    2010/2/5 試してみるわ 女


    これをlinux上でrubyでUTF-8として読み込む方法です。

    以下をなんとかします
    ・Shift-JISをUTF-8に変換する
    ・タブ区切りファイルを読み込む
    ・最初の行をなんとかする

    FasterCSVを利用します。
    インストールは
    gem install fastercsv
    でOK。

    csvファイルでヘッダーがない場合は、以下のような感じで利用します。

    require 'fastercsv'
    FasterCSV.foreach('test.csv') { |row| p row}

    csvを以下のような配列を得ることができます。

    ["2010/2/5", "お試しするぞう", "男"]
    ["2010/2/5", "試してみるわ", "女"]


    で、今回の場合は以下のような感じにします。

    require 'fastercsv'
    FasterCSV.parse(NKF.nkf('-w -Lu',open('test.tsv').read),
    :col_sep=>"\t",
    :headers => true) {|row|
    data = row.fields
    p data
    }

    これで同じように
    ["2010/2/5", "お試しするぞう", "男"]
    ["2010/2/5", "試してみるわ", "女"]
    となります。

    ・Shift-JISをUTF-8に変換する
     このために
     NKF.nkf('-w -Lu',open('test.tsv').read)
     でファイルの内容をUTF-8の文字列として取得します。
     ファイルを直接読むならば
      FasterCSV.foreach
     でよいのですが、文字列を扱うので
      FasterCSV.parse
     とします。

    ・タブ区切りファイルを読み込む
     :col_sep=>"\t"
     を指定すればOKです。

    ・最初の行をなんとかする
     :headers => true
     を指定することで先頭行をheaderとすることができます。
     ただこれだけだとcsvの値が配列ではなく

    #<FasterCSV::Row "日付":"2010/2/5" "お名前":"お試しするぞう" "性別":"男">
    #<FasterCSV::Row "日付":"2010/2/5" "お名前":"試してみるわ" "性別":"女">

     のようにFasterCSV::Rowオブジェクトになってしまいます。
     これだと各カラム内容を取得するためには
     row['日付']
     のようにする必要があります。
     ヘッダー情報が絶対変わらないのならばいいのですが、そうとも限らないとこれはこまるので
     data = row.fields
     で配列を取得しています。

    前処理で文字変換と一行目除去をしておけばここまでしなくてもよいのですけどね。

    2010-01-26

    デジタルハリネズミ

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク


    一言で片付けてしまえばデジタルトイカメラなのですが、取れる画像がなんかレトロ感があるいい感じのものが取れるようなのでキニナルのです。
    性能ははっきりいって低いのですがいい味のために必要なスペックな感じでキニナルのです。

    詳細は以下を見てください。
    http://www.superheadz.com/digi2/index.php

    Rails2.3でActiveRecordのセッションを削除する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

    を今、読んでいるのですがそこでActiveRecordでsessionを管理している際のsession削除の方法として
    CGI::Session::ActiveRecordStore::Session.delete_all(["sessions.updated_at < ?",3.days.ago])
    を実行すると紹介していたのですが、Rails2.3では
    CGI::Session::ActiveRecordStore

    ActiveRecord::SessionStore
    に変更されたようです。
    なので
    ActiveRecord::SessionStore::Session.delete_all(["sessions.updated_at < ?",3.days.ago])
    とする必要があるようです。

    2010-01-22

    rcovの結果をブラウザで確認する

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    rcovはrubyのテストのカバー率を集計してくれるツールです。

    railsを使うなら、テストをちゃんとやってこそ意味があると思っているのですが、
    なかなかテストを書くモチベーションは上がりにくいものです。

    しかしなんらかの指標があれば、テストを書くモチベーションも上がります。
    rcovはそんな指標を提供してくれるわけです。

    インストール方法や使い方は、簡単に調べられるわけなのでとくに書きません。

    rcovを実行するとrailsの場合、
    RAILS_ROOT/coverage
    に結果をいい感じのhtmlで結果レポートを作成してくれます。

    windowsで開発しているならばディレクトリ内のindex.htmlをブラウザで見ればよいわけですが、linux環境に対してsshでログインして開発しているとそういうわけにもいきません。

    そこで最初は
    publicにcoverageディレクトリをコピーして
    ./script/server
    としてブラウザから
    http://x.x.x.x:3000/coverage
    で確認したところ、私の環境ではなぜかcssなどがうまく読み込まれず、がっかりな表示なりました。

    それを解決してくれたのが、以下のページです。
    http://d.hatena.ne.jp/babie/20071101/1193908806

    script/rcov-server
    という以下のようなスクリプトを用意します。
    #!/usr/bin/env ruby
    require "webrick"
    
    __DIR__ = File.dirname(__FILE__)
    s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot => "#{__DIR__}/../coverage")
    trap('INT'){ s.shutdown }
    s.start
    

    rcovの結果を確認したいときは、
    script/rcov-server
    を実行して
    ブラウザから
    http://x.x.x.x:8000/coverage
    を確認するとステキな結果が確認できるというわけです。

    2010-01-19

    rspecにファイルアップロードのテストを書く

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    Railsさんアプリでファイルアップロードのテストの書き方です。

    以下のようなアップロードしたファイルを/tmpの下に保存するコントローラーがあるとします。
    class TestController < ApplicationController
      def index
      end
    
      def upload
        file=params[:file]['csv']
        @filename = params[:file]['csv'].original_filename
        File.open("/tmp/#{@filename}","wb"){ |f| f.write(file.read) }
      end
    end
    
    このコントローラー用のviewを以下のような感じで用意します。
    <% form_tag({:action => 'upload'},{:class=>'form',:multipart=>true}) do %>
    <%= file_field "file","csv" %>
    <%= submit_tag("upload") %>
    <% end %>
    
    specファイルは以下のような感じになります。
    describe TestController do
      describe "fileをポストする" do
        before(:each) do
          @file = fixture_file_upload "test.csv", "text/comma-separated-values"
          post 'upload',:file => {"csv"=>@file}
        end
        after(:each) do
          File.delete("/tmp/test.csv")
        end
        it "/tmpにファイルが保存される" do
          FileTest.exist?("/tmp/test.csv").should be_true
        end
      end
    end
    
    ファイルアップロードのテストにはfixture_file_uploadを使うようです。
    fixture_file_uploadで指定するファイルは
    spec/fixtures/
    にあると見なされるようです。
    viewで
    file_field "file","csv"
    とした部分は
    post 'upload',:file => {"csv"=>@file}
    と指定すればよいようです。

    2010-01-13

    RailsでRead OnlyなModelをいっぱい作る

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    RailsでRead OnlyなModelを使うには
    acts_as_readonlyable
    というプラグインを使うという方法があるようですが、2.3.4では動かない気配です。
    こちらを改造して使うには、
    http://hisme.net/~masaki/blog/article/show/41
    が参考になります。

    プラグインを使わない方法として
    http://lunatear.net/archives/001089.html
    という方法もあります。

    2.3.4を使っていてプラグインに手を入れるのがちょっと面倒でさらにいっぱいRead OnlyなModelを使いたいと思ったのでプラグインを使わない方法を参考にさせていただき以下のような感じでやってみました。

    app/models/read_only.rb
    を以下のような感じで作ります。
    class ReadOnly < ActiveRecord::Base
      abstract_class = true
    
      def readonly?
        true
      end
    
      def before_destroy
        raise ActiveRecord::ReadOnlyRecord
      end
    
      def self.delete(id)
        raise ActiveRecord::ReadOnlyRecord
      end
    
      def self.delete_all(conditions)
        raise ActiveRecord::ReadOnlyRecord
      end
    
      def self.destroy_all(conditions)
        raise ActiveRecord::ReadOnlyRecord
      end
    
    end
    
    そしてRead Onlyにしたいモデルを以下のように書きます。
    class Test < ReadOnly
    end
    

    ReadOnlyクラスに
    abstract_class = true
    をつけるのがポイントでした。

    2010-01-03

    DjangoとRailsの個人的感想

    このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
    最近、DjangoとRailsをそれぞれ軽く触っています。

    完全に個人的な意見で参考にならないとは思いますが
    両方使った上での個人的な感想は
    本当ならばDjangoだけを利用したいけど仕事で使うならばRailsかなぁ
    といった感じです。

    個人的にはDjangoの方がしっくりくるものがあります。

    Djnagoのいいと思っているところをあげてみると
    ・言語的にPythonの方がRubyの方が好き
     完全に個人的な趣味です
     どちらも優れた言語だと思っているのですが、
     誰が書いても似たようなコードになるような言語仕様であるPython
     多様性は善ということで同じコトをいろいろ表現できるRuby
     とそれぞれのポリシーのうちPythonのポリシーの方が個人的に好きという感じです。
    ・フレームワークとしてすっきりまとまっている気がする
     RailsはActiveRecordなどちょっと書くだけでいろいろ動いちゃうのがちょっとなじめないので
     書かなければならない量がDjangoの方が個人的感覚にはあっている感じです。
    ・Google App Engineで使える
     Railsも使えるみたいですが、Ruby on Rails on JAVAで動くということなので
     ちょっとonし過ぎな印象を持っています。

    Railsのいいと思うところは
    ・Migration
     個人的には、Migration仕組みはとてもステキだと思っています。
     DjangoにもsouthというMigrationのような機能をもつツールもあるようですが、
     Migrationよりかはちょっと面倒な印象です。(使っていないで言っています。)
     southについては
     http://nakagami.blog.so-net.ne.jp/2009-12-10
     が参考になります。
    ・テスト関連がすっきりしている気がする
     modelやcontrollerを書いたらテストをどこにテストを書くのかとかがDjangoに比べて明確な印象です。
     テストをしっかりやりなさい!という意思が感じられるのがステキな気がします。
     またrspecの存在もステキな気がします。
     pythonにもpyspecというのもあるのですが、rspecに一日の長がある感じがします。
     pyspecについては
     http://pyspec.codeplex.com/wikipage?title=Home_jp&referringTitle=Home
     が参考になります。
    ・情報量が多い
     DjangoよりもRailsの方が情報が多いです。Railsの方が調べた時の見つけやすさ気がします。

    ということで
    個人的にはGoogle App Engineを使いたいのでDjangoが本当はいいのだけど
    Migrationによるスキーマ管理からテストまでの開発の全体を通した開発のしやすさと情報の多さから仕事ではRails使った方がいいかなぁと思ったわけです。

    逆にMigration相当の便利なツールがあれば
    仕事でもDjangoを使ってもよいのかなぁとか思ったりしています。

    完全に個人的な感想でした。

    ちなみに

    はDjangoのことを知る上ではすごく参考になりました。
    ネットでちょっとDjangoのことを調べてから読むと全体像がすごく分かりやすく把握できました。
    そしてそんな機能もあったのねと関心もしてみました。