Monday, December 07, 2009

明けない夜はない

Twitterの@abekatsuをfollowしてくださっている方はまたかと思われるが,12月5日に今シーズンのJ League全日程が終了した。 3年連続J1リーグ制覇の鹿島アントラーズ,2年連続2位終了の川崎フロンターレとなったが長年J2を追っている自分にとって何よりもまず,7シーズンぶりのJ1昇格となるベガルタ仙台,11シーズンぶりのJ1昇格の湘南ベルマーレはおめでとうございますと,述べたい。いままでけさ位,とかデジマーレひらつー化と卑下していた,仙台と湘南がようやくJ1の舞台に復帰できたことを嬉しく思いたい。

一方,勝ち点1の差で昇格を果たせなかったヴァンフォーレ甲府。そんな中,メインスポンサーのはくばくさんのチラシ。

下を向くな

こんなすばらしいスポンサーに恵まれた,ヴァンフォーレ甲府がうらやましい。こんなスポンサーになりたい。
明けない夜はない。昨年ゴール1つの差でJ1昇格を逃したベガルタ仙台のサポーターから,ヴァンフォーレの2010年のJ1昇格を期待して,また翌シーズンの熱き戦いを味わいたい。

2009Jリーグアウォーズの再放送の日時を確認せねば。

Monday, November 30, 2009

NatsuLiphoneとRead It Laterとの連携 (1)

NatsuLiphoneを使っている際に,TimelineにURLが付いているのを読み返したいとき,無闇にふぁぼったりして,favoriteなのか,ただ単なるreminderなのか,よくわからない状況で使っていました。

折角,NatsuLiphoneのsourceが公開されているので,Read It LaterのAPIを連携させて,「web siteを後で読む」(Read It Laterとの連携機能)を実装してみました。

Read It LaterのAPI Keyの関係上,まだdiffを公開できませんが,ここ数日でNatsuLiphoneの作者様や,Read It Laterと連絡してみて,何とか公開できるようにしてみます。

見せられる部分のキャプチャ画面。

 
下のツールバーに+ボタンつけました。 UIActionSheetでRead It Laterに登録するボタンを出しました(キャンセルもできます)。  
Read It Laterのアカウント設定画面入り口 Twitterと同じようにRead It Laterのアカウントを設定します。 アカウントが間違っていると,Alertで警告されます(アカウント登録キャンセル機能も実装しないといけないことに今気付いた)。

さて,NatsuLiphoneのsourceは,Model,View,Controllerとの概念をしっかり分けていて,比較的楽に読むことができたのですが,一点だけ気になる点。

ntlniph/NatsuLion/models/network/NTLNHttpClient.mの
- (void)requestSucceeded {
 // implement by subclass
}

- (void)requestFailed:(NSError*)error {
 // implement by subclass
}
の箇所。やはり,これらの2つの関数をdelegate protocolで定義し,このdelegate protocolをsub classは実装するという形にすれば,もっと綺麗になるかなと思いました。Objective-Cに慣れるための練習問題として,やってみるのも面白いかと思います。

Friday, November 27, 2009

Rails Integration Test (2) - restful_authentiaction plugin を導入した際の integration test の書き方

Railsでrestful_authentication plugin を導入したら,今までのintegration testが 通らなくなった。理由は,login sessionが確立されていないかだが,どのように login sessionを integration test内で確立させるか?

% script/generate authenticated user sessions
で,sessions_controllerを作成したとき,test/functional/sessions_controller_test.rbが作成され,
  def test_should_logout
    login_as :quentin
    get :destroy
    assert_nil session[:user_id]
    assert_response :redirect
  end
というのがあるので,login_as methodが利用できると考えられる。しかし,単純にlogin_asを呼びだしても,
  1) Error:
test_comming_and_going_editing_acount_view_and_creating_new_category(AccountCategoryFlowsTest):
NoMethodError: You have a nil object when you didn't expect it!
The error occurred while evaluating nil.session
    /lib/authenticated_test_helper.rb:4:in `login_as'
    test/integration/account_category_flows_test.rb:17:in `test_comming_and_going_editing_acount_view_and_creating_new_category'
と怒られる。そこでlogin_as methodがどのように定義されているかを確認すると,
lib/authenticated_test_helper.rb
  def login_as(user)
    @request.session[:user_id] = user ? (user.is_a?(User) ? user.id : users(user).id) : nil
  end
とあるように,@requestを事前に準備していなければならない。その答えは,Rails forumの次のdiscussionにあった。 how to get a user in a functional test, with AuthenticatedSystem? より,
  def setup
    @request    = ActionController::TestRequest.new
  end
setupで,ActionController::TestRequestのインスタンスを@requestに作成しておけば login_as を実行しても怒られなくなった。

Tuesday, November 17, 2009

UbuntuでのHOME directoryの暗号化(インストール後)

Mac OS Xには,FileValut機能によって,ホームフォルダを暗号化する機能がありますが,同様にThinkPad X60s上に導入したubuntuの/home/$USERも暗号化させたいもにです。そこで, Ubuntu's Encrypted Home Directory: A Canonical Approach to Data Privacy を参考にして,やってみました。ハマった点が2箇所あるので,手順を引用しながら説明します。

該当箇所は "Ubuntu 9.10 Live Migration to an Encrypted Home Directory" の箇所です。


rm -rf $HOME.old

を実行する前まではやりなおすことができるので,慎重に実行してください。こういう作業を行う際には紛失してもかまわないように,データのバックアップを実行して,外部に保存してください。

以下の作業はTTY端末で実行した方が安全です。gnomeセッションが残っていると,一部のファイル.gvfs/にアクセスする際に問題が発生します。Login画面の所でにCTRL-ALT-F1を同時押しして,TTY端末に落としましょう。

作業開始前,または途中作業がわからなくなって最初からやり直す場合に,$HOME/.Private,$HOME/Private, $HOME/.ecryptfs を削除しておきます。


% sudo rm -rf $HOME/.Private $HOME/Private $HOME/.ecryptfs

セットアップを開始します。

% encryptfs-setup-private
2010年5月8日訂正。h12o様より,ご指摘いただきました。「encryptfs-setup-private」ではなく「ecryptfs-setup-private」です。
% ecryptfs-setup-private

login passphrase,mount用pass phraseが聞かれますので,適切に入力します。

一度,log outしlog inしなおして,$HOME/Private がmountされていることを確認しておきます。


% exit
... log in again
% mount | grep "$USER.*ecryptfs*" <- ここで $HOME/Privateがmountされているかどうか確認できます。


これで,$HOME/Privateの中が暗号化されているわけです。これを何とか$HOMEを対象にしたいのが目的です。

encryptするHOMEの内容を$HOME/Privateにsyncしておきます。


% rsync -aP --exclude=.Private/ --exclude=Private --exclude=.ecryptfs $HOME/ $HOME/Private


sync しておいて,$HOME/Private を umount して,一旦 logout します。

% sync
% ecryptfs-umount-private
% exit

再login後,eCryptfsのconfiguration directoryを設定します。


% ecryptfs-umount-private
% cd /
% sudo mkdir -p /home/.ecryptfs/$USER
% sudo mv $HOME/.ecryptfs /home/.ecryptfs/$USER

ここから,新しいhome directoryを設定します。


% sudo mkdir -p -m 700 /home/$USER.new
% sudo chown $USER:$USER /home/$USER.new <- user/groupは適切な値にしておいてください。
% sudo mv $HOME/.Private /home/.ecryptfs/$USER
% sudo ln -s /home/.ecryptfs/$USER/.ecryptfs /home/$USER.new/.ecryptfs

一旦,$HOMEをbackupします,


% sudo mv $HOME $HOME.old

新しいHOME directoryに移行します。


% sudo mv /home/$USER.new $HOME
% echo $HOME > $HOME/.ecryptfs/Private.mnt
% sudo ln -s /usr/share/ecryptfs-utils/ecryptfs-mount-private.txt $HOME/README.txt
% sudo chmod 500 $HOME

一旦,log outして再log in後,configuration direcotry (.ecryptfs) と .Private に対してsymbolic linkを貼ります。


% exit
... log in
% ln -s /home/.ecryptfs/$USER/.ecryptfs $HOME/.ecryptfs
% ln -s /home/.ecryptfs/$USER/.Private $HOME/.Private <- これがないとマウントできない。

最後に,元のHOMEを削除します。


% sudo rm -rf $HOME.old

これで,ThinkPad X60sを持ち歩いても大丈夫になったかなと思います。

Monday, October 26, 2009

フィードバックが得られない文化を維持していくことは難しい

[社会][web&リアル]文化の地域格差は人の格差か?— はてブついでに覚書。
文化の発信はどこからでもできるが,文化は中央に集約してしまう。そりゃそうだ。観客の数が違う。数が多いとフィードバックが多い。文化は発信だけでなく,反応もなければ成立しない。
例えば,地元鹿角市には正月2日に大日霊貴神社(大日堂,だいにちどうといった方が地元では通じるだろう。)で舞を奉納している。うちの集落谷内では,「五大尊舞」という演目が伝承されている。この日は県内の報道機関やアマチュアカメラマンが一同に集り,カメラのフラッシュがたかれる。
参考 大日堂舞楽(鹿角市)がユネスコ無形文化遺産の「代表一覧表」に記載されました
伝聞のように書いてあるのは,実は私は全く知らない。実は集落の人,特に同年代の方々を全く知らないのだ。自分が参加していないのが悪いんだろうと言われるが,引きこもり的な資質もあり中々進んでいけない。集落の方々が共有して持っている少年青年期に体験したことを私は全くしていない。理由は簡単。父が転勤族のため,小・中・高校と全て違うところで生活してきたからだ。
最初に戻ろう。文化の発信は1人でもできる。しかし,必ずしもフィードバックが得られるとは限らない。まだ東京の方が可能性がある。
文化の格差というよりも,文化を共有できる関係を求めるのが人間の性だと思う。San Jose近郊のBay areaに集まる人や,東京に集まる人。などなど。

Tuesday, October 13, 2009

Add new user (2) - Reading Tracks (5)

今日の課題


        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
Userが登録されているにもかかわらず,admin以外のユーザが登録しようとしても失敗させるためのケース。

        user = User.new(params['user'])
で,モデルUserのインスタンスを生成し,その次の評価で,作成するインスタンスのvalid性を評価している。

        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end
validでないUserインスタンスならば,"/user/new" にリダイレクトさせて,その際にerror内容を表示させるのだろう。

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
ここで,最初のuser登録かチェックしている。つまり,最初に登録されるユーザは必ずadmin権限を持つようになっている。

        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
最後に,新しく生成したインスタンスが保存できるのならば,redirect_back_or_home され,処理を終える。

おもしろい。このまま,tracks Applicationの実装を読み進めていこう。それと並行してRails applicationの試作を行ってみたい。

Monday, October 12, 2009

Add new user - Reading Tracks (4)

今日の課題

ユーザ登録はどのようにやっているのか?具体的には,


192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
ここで,どんな処理をしているのか?
早速,user_controller.rb の該当するコードを参照してみる。

  # Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
  #               -u admin:up2n0g00d
  #               -d '<request><login>username</login><password>abc123</password></request>'
  #               http://our.tracks.host/users
  #
  # POST /users
  # POST /users.xml
  def create
    if params['exception']
      render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
      return
    end
    respond_to do |format|
      format.html do
        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
        
        user = User.new(params['user'])
        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
      end
      format.xml do
        unless User.find_by_id_and_is_admin(session['user_id'], true)
          render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
          return
        end
        unless check_create_user_params
          render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
          return
        end
        user = User.new(params[:request])
        user.password_confirmation = params[:request][:password]
        if user.save
          render :text => "User created.", :status => 200
        else
          render_failure user.errors.to_xml
        end
        return
      end
    end
  end  
まず最初の例外処理を見てみる。

    if params['exception']
      render_failure "Expected post format is valid xml like so: <request><login>username</login><password>abc123</password></request>."
      return
    end
想定外のXML文書が来たかどうかだと思う。想定外かどうか判断するには,モデルuserを参照するのだろう。validates_presence_of には,:login と :password があり,:login は 3文字以上80文字以下などなどと制限を設けている。そして失敗したら,render_failure で失敗理由を明示し,元に戻っている。
実際のテストコードでも,このような内容のテストが行なわれている。test/functional/users_controller_test.rb の以下のテストだ。

  def test_create_with_invalid_password_does_not_add_a_new_user
    login_as :admin_user
    assert_no_difference(User, :count) do
      post :create, :user => {:login => 'newbie', :password => '', :password_confirmation => ''}
    end
  end
  
  def test_create_with_invalid_password_redirects_to_new_user_page
    login_as :admin_user
    post :create, :user => {:login => 'newbie', :password => '', :password_confirmation => ''}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
  
  def test_create_with_invalid_login_does_not_add_a_new_user
    login_as :admin_user
    post :create, :user => {:login => 'n', :password => 'newbiepass', :password_confirmation => 'newbiepass'}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
  
  def test_create_with_invalid_login_redirects_to_new_user_page
    login_as :admin_user
    post :create, :user => {:login => 'n', :password => 'newbiepass', :password_confirmation => 'newbiepass'}
    assert_redirected_to :controller => 'users', :action => 'new'    
  end
なるほど,最初のテストではinvalidなpasswordを持つuserをUserに追加させていない。他の3つは,invalidな:login,:password を持つuserの作成に対するrequestに対して, /users/new に redirect されているかどうかをテストしている。(警告メッセージが出ているのかどうかテストするにはどうすればいいのだろうか。)
次の行からは,
respond_to do |format|
と始まっているように,responseを作成している箇所であることを確認して,ここまでとする。早速以下の処理内容を理解できないので,じっくりと把握していきたい。

        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end

HTTP POST Method - Reading Track (3)

今日の課題

POSTの内容はどうなっているのか?誰がPOSTの内容をXML文書に成形しているのか?


<request><login>username</login><password>abc123<password></request>

POSTリクエストを送信したときのパケットをキャプチャしてみた。TCP payloadの内容を以下に記す(passwordの箇所は"password"でマスクした)。


POST /login HTTP/1.1
Host: 192.168.1.101:3000
User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.3) Gecko/20091007 Ubuntu/9.10 (karmic) Firefox/3.5.3 GTB5
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-2022-JP,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://192.168.1.101:3000/login
Cookie: preferred_auth=database; tracks_login=admin; _tracks_session_id=e22a17f51266e7fa3b30fb6cd3def1fb
Content-Type: application/x-www-form-urlencoded
Content-Length: 139

authenticity_token=2fc78f9b3f11d9447cdc5719f19742bdfe9b531f&user_login=admin&user_password=password&user_noexpiry=on&login=Sign+In+%C2%BB

Studying HTTPは,HTTP/1.1 Post Methodについて解説していただいている。そこを参照すると,Content-Type: application/x-www-form-urlencoded はエンテティボディのメディアタイプとして一般的に利用されているタイプの一つで,今回のUser-Agent (Firefox 3.5.3) は,この方式でエンティティを送信しているものと考えられる。このように,規格があるのならば,このようなRequestパケットを受信したRailsアプリケーションがurlencodedなデータから,validなXML-documentを生成するのは簡単だろう。他のブラウザではどのような形式で送信するかわからないが,そこのところはRailsでwrapperしているものと考えればいいのだろう。

Rails Application - Reading Tracks (2)

users_controller.rb - Tracks reading.

user_controller.rb

Track applicationでユーザー(admin)を登録した時のコンソール出力から何が起きているか確認してみる。
まず,user_controller.rb のアクション new の内容を確認する。

  # GET /users/new
  def new
    if User.no_users_yet?
      @page_title = "TRACKS::Sign up as the admin user"
      @heading = "Welcome to TRACKS. To get started, please create an admin account:"
      @user = get_new_user
    elsif @user && @user.is_admin?
      @page_title = "TRACKS::Sign up a new user"
      @heading = "Sign up a new user:"
      @user = get_new_user
    else # all other situations (i.e. a non-admin is logged in, or no one is logged in, but we have some users)
      @page_title = "TRACKS::No signups"
      @admin_email = User.find_admin.preference.admin_email
      render :action => "nosignup", :layout => "login"
      return
    end
    render :layout => "login"
  end
userがまだ未定義なので,Title と headline,Userモデルのインスタンスを確保している。そして,最後にある render :layout => "login" が view の提供のキーとなるだろう。ActionController::Baseのrenderメソッドを確認すると,"login"というカスタムレイアウトを用いれ,response bodyを作成していることがわかる。ここで,app/views/layout/login.html.erb の中身を見てみる。
@page_title というのが出てきた。先ほど指定した @page_title が埋めこまれている。おそらく <%= render :partial => "shared/footer" %> は共通のfooterを埋めこんでいるのだろう。
さて,<%= yield %> は何ものか?これはActionController::Layoutのクラスメソッドの説明を読んで考えてみると,どうやらtitleとかfooterは共通にしたいけど,login 画面は個別のviewを埋めこみたいと考えているのだろうか。ここで,"/users/new" リクエストでアクセスしてきたことを思いだす。app/views/users/new.html.erb が定義されてあった。 ここでユーザーAccount Signupのviewを生成しているのだなと確認できる。
さて,submitボタンを押したときに,コンソール画面には以下の内容が表示されている。

192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
再び users_controller.rb に戻ろう。"POST /users" リクエストなので,create メソッドが実行される。create メソッドの内容は以下の通り。

  # Example usage: curl -H 'Accept: application/xml' -H 'Content-Type: application/xml'
  #               -u admin:up2n0g00d
  #               -d 'usernameabc123'
  #               http://our.tracks.host/users
  #
  # POST /users
  # POST /users.xml
  def create
    if params['exception']
      render_failure "Expected post format is valid xml like so: usernameabc123."
      return
    end
    respond_to do |format|
      format.html do
        unless User.no_users_yet? || (@user && @user.is_admin?)
          @page_title = "No signups"
          @admin_email = User.find_admin.preference.admin_email
          render :action => "nosignup", :layout => "login"
          return
        end
        
        user = User.new(params['user'])
        unless user.valid?
          session['new_user'] = user
          redirect_to :action => 'new'
          return
        end

        first_user_signing_up = User.no_users_yet?
        user.is_admin = true if first_user_signing_up
        if user.save
          @user = User.authenticate(user.login, params['user']['password'])
          @user.create_preference
          @user.save
          session['user_id'] = @user.id if first_user_signing_up
          notify :notice, "Signup successful for user #{@user.login}."
          redirect_back_or_home
        end
        return
      end
      format.xml do
        unless User.find_by_id_and_is_admin(session['user_id'], true)
          render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
          return
        end
        unless check_create_user_params
          render_failure "Expected post format is valid xml like so: usernameabc123."
          return
        end
        user = User.new(params[:request])
        user.password_confirmation = params[:request][:password]
        if user.save
          render :text => "User created.", :status => 200
        else
          render_failure user.errors.to_xml
        end
        return
      end
    end
  end  

Signup » を押すと,POSTリクエストが生成され,Rails アプリケーションには

<request><login>username</login><password>abc123</password></request>
とvalidなXML形式がcontrollerに送られている模様。誰がXML形式に成形しているのだろうか?

Thursday, October 08, 2009

Rails Application - Reading Tracks (1)

Rails Application Tracks を読む

ここでは,Rails Application, Tracksの振舞いを見てみる。
Tracks を動かすのは簡単だ。自分は Rails 2.3.3 の環境を構築して,SQLite3,libsqlite3-ruby をインストールすれば準備完了。Download ページから 1.7 release を展開して,rake db:migdate を実行した後,server を実行する(databaseのconfigは用意されてある)。
起動してみて,webブラウザでアクセスすると,コンソールに以下の内容が表示される。


192.168.1.102 - - [08/Oct/2009:21:57:59 JST] "GET / HTTP/1.1" 302 97
- -> /
192.168.1.102 - - [08/Oct/2009:21:57:59 JST] "GET /login HTTP/1.1" 302 101
- -> /login
192.168.1.102 - - [08/Oct/2009:21:58:00 JST] "GET /users/new HTTP/1.1" 200 2523
- -> /users/new
どうやら login controller を経由して,users_controller の new アクションを実行している模様。 config/routes.rb の内容を確認してみると,

ActionController::Routing::Routes.draw do |map|
  map.with_options :controller => 'login' do |login|
    login.login 'login', :action => 'login'
    login.formatted_login 'login.:format', :action => 'login'
    login.logout 'logout', :action => 'logout'
    login.formatted_logout 'logout.:format', :action => 'logout'
  end
  # snip 
とあるので,login controller の login action を呼びだしている模様。login.login とか login.formatted_login とかが何を表現しているのかがよくわからない。これは "/login" や "login.m" というリクエストに対して名前をつけたと考えていいのだろうか?
このことを確認するため,ユーザ登録後に "/login","/login.m","/login.xml" というリクエストを発行した。login_controller の login method の最後の方に,こんな表示がある。

      respond_to do |format|
        format.html
        format.m   { render :action => 'login_mobile.html.erb', :layout => 'mobile' }
従って最後の "/login.xml" は xml 形式のrespondが定義されていないので,何も表示されない。実際に "/login.xml" では何も表示されない。また "/login.m" ではいかにも携帯電話用のログイン画面が表示された。
さて,login_controller.rb の内容に戻ってみる。

  def login
    if openid_enabled? && using_open_id?
      login_openid
    else
      @page_title = "TRACKS::Login"
      case request.method
      # snip
        when :get
          if User.no_users_yet?
            redirect_to :controller => 'users', :action => 'new'
            return
          end
      end
      # snip
    end
  end
とあるので,ユーザを未登録の場合,users controller の action new へ redirect されているのがわかる。

次にユーザ(admin)を登録してみる。コンソール出力は以下の通り。


192.168.1.102 - - [08/Oct/2009:22:52:51 JST] "POST /users HTTP/1.1" 302 92
http://192.168.1.101:3000/users/new -> /users
192.168.1.102 - - [08/Oct/2009:22:52:52 JST] "GET / HTTP/1.1" 200 10825
http://192.168.1.101:3000/users/new -> /
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /stylesheets/cache/bundle.css?1255009973 HTTP/1.1" 200 29449
http://192.168.1.101:3000/ -> /stylesheets/cache/bundle.css?1255009973
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /behaviours/index.js HTTP/1.1" 304 0
http://192.168.1.101:3000/ -> /behaviours/index.js
192.168.1.102 - - [08/Oct/2009:22:53:01 JST] "GET /javascripts/cache/bundle.js?1255009981 HTTP/1.1" 200 247440
http://192.168.1.101:3000/ -> /javascripts/cache/bundle.js?1255009981
次から users_controller.rb の内容を追ってみようと思う。

Rails Integration Test (1)

A Guide to Testing Rails Applications

5. Integration Testing

Integration テスト: (複数の)コントローラ間の通信をテストすること。important work flowsをテストするのに使われる。
RailsにはIntegrationテスト用のスケルトンコード作成機能が備わっている。


% script/generate integration_test user_flows
      exists  test/integration/
      create  test/integration/user_flows_test.rb
内容は,こんな感じ。

require 'test_helper'

class UserFlowsTest < ActionController::IntegrationTest
  fixtures :all

  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
end
ここで,fixturesというのが出てきた。

5.1 Helpers Available for Integration Tests

どんな helper が使えるのかという内容。リンク先のテーブル参照。

ここまで読んで,その後もざっと流し読みしたが,自分の中のRailsやTDDについてのイメージがまだ浮かんでこないので,ここで実際のアプリケーションに立ち入って理解していきたいと思う。

Monday, October 05, 2009

Rails Functional Test (2)

A Guide to Testing Rails Applications

昨日の復習


  test "should create post" do
    assert_difference('Post.count') do
      post :create, :post => { :title => 'Hi', :body => 'This is my first post.' }
    end

    assert_redirected_to post_path(assigns(:post))
    assert_equal 'Post was successfully created.', flash[:notice] 
  end

というテストコードを書いた。最初の"post :create, :post => { :title => 'Hi', :body => 'This is my first post.' }" はpostコントローラにcreate アクションを実行。":post" symbol にpost controllerのcreate actionに対する引数を与えた。(パラメータは{ :title => 'Hi', :body => 'This is my first post.' })
次のassert文 "assert_redirected_to post_path(assigns(:post))" 。よくわからないが,"format.html { redirect_to(@post) }" に関連したテストなのだろうか?
最後のassert文,"assert_equal 'Post was successfully created.', flash[:notice]" で,flash[:notice]に "Post was successfully created" が渡されているかどうかをテスト。post_controller.rb を見ると,flash[:notice] に "Post was successfully created" が引き渡されていた。

  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        flash[:notice] = 'Post was successfully created.'
        format.html { redirect_to(@post) }
        format.xml  { render :xml => @post, :status => :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }

続き。

4.6 Testing Views

viewのテストとして,key HTML elementsの存在やコンテンツに対するassertingをすることによって,viewのテストを行う。
"assert_select" を使うことで,simpleだけどpowerfulなsyntaxを使うことができる。
assert_selectの形式:

assert_select (selecter, [equality], [message]) ensures that the equality condition is met on the selected elements through the sector. The selector may be a CSS selector expresion (String), an expression with substitution valutes, or an HTML::Selector object.
assert_select (element, selecter, [equality], [message]) ensures that the equality condition is met on all the selected elements through the selector starting from the element (instance of HTML::Node) and its descendants.

  assert_select 'title', "Welcome to Rails Testing Guide"
あまり用途がわからない。他の用法等を参照してみる。

Sunday, October 04, 2009

Rails Functional Test (1)

A Guide to Testing Rails ApplicationsFunctional Tests for Your Controllersから再開。

4. Functional Tests for Your Controllers

Rails における,functional test: controller単体の様々なアクションをテストすること。Controllersはimcoming web-requestをアプリケーションに受け渡し,その結果rendered viewを返答する。

4.1 What to Include in your Functional Tests

テストすべき項目
  • was the web request successful? (日本語では何といえばいい?成功したweb request?ちゃんとしたweb requestであるか?)
  • was the user redirected to the right page? 正しいページにリダイレクトされたか?
  • was the user successfully authenticated? (ユーザーはちゃんと認証されたか?)
  • was the correct object stored in the response template? (正しいオケクトがレスポンステンプレートの中に記録されたか?)
  • was the appropriate message displayed to the user in the view? (適切なメッセージがユーザにview表示されたか?)
以前,ScaffoldでPostモデルを作成したので,その際に作成したコントローラのコードや機能をここではテストする。test/functional ディレクトリにテスト posts_controller_test.rb があるのでそれを参照してみる。
tutorialでは test_should_get_index というメソッドが定義されているが,ここでは

  test "should get index" do
    get :index
    assert_response :success
    assert_not_nil assigns(:posts)
  end

となっているので今回も,これを見てみる。
"should get index"テストでは,Railsは "index" アクションを要求して, request が成功したかどうかを,そして更に妥当な posts インスタンス変数を割りあてているかどうかテストを確認している。
"get" メソッドはweb requestを発行して,結果をレスポンスに反映させている。It (="get" method) accepts 4 arguments:
  • リクエストするコントローラのアクション。文字列,もしくはsymbol形式で与える。
  • (Optional)アクションに引き渡すリクエストパラメータのオプショナルハッシュ (eg. クエリー文字列やポスト変数)。
  • (Optional)リクエストに沿った内容のセッション変数のハッシュ
  • (Optional)フラッシュ値(メッセージ)
例題。:show アクションを呼びだす。その際,"12"というidをパラメータとして与え,セッションにおける"user_id"を5と指定する。

  get(:show, {'id' => "12"}, {'user_id' => 5})
例題。:view アクションを呼びだす。その際,"12"というidをパラメータとして与える。セッションは確立されないとするが,フラッシュメッセージが添えられている。

  get(:view, {'id' => "12"}, nil, {'message' => 'booya!'))
ここで先に進む前に,Post モデルに "validates_presence_of :title" を追加したことを思い出す。
If you try running test_should_create_post test from posts_controller_test.rb it will fail on account of the newly added model level validation and rightly so.
と書いてあるように,Testがパスできるように test_should_create_post に手を加える。

  test "should create post" do
    assert_difference('Post.count') do
      post :create, :post => { :title => 'Some title' }
    end

    assert_redirected_to post_path(assigns(:post))
  end

実際にfunctional testを実行してみた。
変更前

/home/abekatsu/webroot/TestingRails% rake test:functionals
(in /home/abekatsu/webroot/TestingRails)
/usr/bin/ruby1.8 -I"lib:test" "/home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/posts_controller_test.rb" 
Loaded suite /home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
F......
Finished in 0.236084 seconds.

  1) Failure:
test_should_create_post(PostsControllerTest) [/test/functional/posts_controller_test.rb:16]:
"Post.count" didn't change by 1.
<3> expected but was
<2>.

7 tests, 9 assertions, 1 failures, 0 errors
rake aborted!
Command failed with status (1): [/usr/bin/ruby1.8 -I"lib:test" "/home/abeka..."]
(See full trace by running task with --trace)
変更後

/home/abekatsu/webroot/TestingRails% rake test:functionals
(in /home/abekatsu/webroot/TestingRails)
/usr/bin/ruby1.8 -I"lib:test" "/home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader.rb" "test/functional/posts_controller_test.rb" 
Loaded suite /home/abekatsu/.gem/ruby/1.8/gems/rake-0.8.7/lib/rake/rake_test_loader
Started
.......
Finished in 0.23919 seconds.

7 tests, 10 assertions, 0 failures, 0 errors

4.2 Available Request Types for Functional Tests

Railsのfunctional テストでサポートされているリクエストタイプ:
  • get
  • post
  • put
  • head
  • delete
get, postでほとんどのテストが書けてしまうだろうとある。

4.3 The Four Hashes of the Apocalypse

先程の5つのメソッドでリクエストが作成されると,次の4つのタイプのハッシュオブジェクトを使用できる。
  • assigns - Any objects that are stored as instance variables in actions for use in views.
  • cookies - Any cookies that are set.
  • flash - Any objects living in the flash
  • session - Any objected in session variables.
使用例

flash["gordon"]           flash[:gordon]
session["shmession"]      session[:shmession]
cookies["are_good_for_u"] cookies[:are_good_for_u]

# Because you can't use assigns[:something] for historical reasons:
assigns["something"]      assigns(:something) 

4.4 Instance Variables Available

functional testに次の3つのインスタンス変数にアクセスできる。
  • @controller – The controller processing the request
  • @request – The request
  • @response – The response

4.5 A Fuller Functional Test Example


  test "should create post" do
    assert_difference('Post.count') do
      post :create, :post => { :title => 'Hi', :body => 'This is my first post.' }
    end

    assert_redirected_to post_path(assigns(:post))
    assert_equal 'Post was successfully created.', flash[:notice] 
  end

Saturday, October 03, 2009

Rails Unit Test

これまでの流れ。 A Guide to Testing Rails Applicationsを読んでいる。

確認


  test "post should not save without title" do
    post = Post.new
    assert !post.save, "Saved the post without a title"
  end

というテストを書いたので,今度は

  test "post can save with title" do
    post = Post.new
    post.title = "Test Title"
    assert post.save, "Saved the post with a title"
  end

というのを書いてみたが, post.title = "Test Title" で怒られる。どう記述すればいいのか。

3.3 What to Include in Your Unit Tests

続き
Unit Testに何を含めればいいのか?

Ideally you would like to include a test for everything which could possibly break. It’s a good practice to have at least one test for each of your validations and at least one test for every method in your model. 理想的にいえば,起こりえる全ての事に大してテストしたい。全てのvalidationに対して少なくとも一つのテストと,全てのメソッドに対しても少くても一つ以上のテストを作成するのが good practice である。
メソッドに対するテストと書いてあるが,具体的にどんなメソッドテストを書くのだろうか?

3.4 Assertions Available

3.5 Rails Specific Assertions

どんなassert式を書けるか。Rails特有のassertionは? リンク先の表を見るのがいい。

Wednesday, September 30, 2009

Rails でテストするのはどうしようかと調べてみる

動機づけ

Railsアプリケーションを作ってみよう。せっかくなのでTest Drivenで。
とりあえず,ここから(A Guide to Testing Rails Applications)読みはじめてみる。訳は適当で,その場その場で気になったことをメモしている程度

1 Why Write Tests for your Rails Applications?

なぜTestを書くのか。

  • Railsはテストを書くのを楽にしてくれるよ。ModelやControllerを作成時に,テストコードのスケルトンも一緒に作ってくれるので,そこからスタートできる。
  • Railsのテスト実行は簡単。リファクタリングしても機能を満たしていることを確認できる。
  • ブラウザのリクエストをシミュレートできるので,ブラウザ使わずにテストできる(ここ重要。)。

2 Introduction to Testing

"To write efficient tests, you’ll need to understand how to set up this database and populate it with sample data."

2.1 The Three Environments

config/database.yml をみると,

  • production
  • development
  • test
と,3つの環境が用意されている。こうすることで,test環境とproduction環境を分けることで,テストデータが実行環境をおかす心配はない。
「rake db:test:prepare で,テスト用データベース環境の構築ができる」。

2.2 Rails Sets up for Testing from the Word Go

test フォルダの下にできるfolder

unit
tests for your models
functional
tests for your controllers
integration
test that invole any anumber of controllers interacting
fixtures
a way of organzizing test date

2.3 The Low-Down on Fixtures

Fixures: a fancy word for sample data.
Here’s a sample YAML fixture file:

# low & behold! I am a YAML comment! 
david: 
  name: David Heinemeier Hansson 
  birthday: 1979-10-15 
  profession: Systems development 

steve: 
  name: Steve Ross Kellock 
  birthday: 1974-09-27 
  profession: guy with keyboard 
ERb allosw you embed ruby code within templates. <% %>タグはRuby codeと認識される。
Fixtures in Action
デフォルトでは text/fixtures 以下にある全てのfixturesを
  • unit test/functional test時に 読みこむ。
  • Remove any exsiting data from the table corresponding to the fixture
  • Load the fixture data into the table
  • Dump the fixures data into a variable in case you want to access it directly
Hashes with Special Powers
Fixtures は 基本的にはハッシュ objectなので,このようなアクセスの方法があるよ。
# this will return the Hash for the fixture named david 
users(:david) 
# this will return the property for david called id 
users(:david).id 
Fixturesからオリジナルのクラスに変換することができるので,そのクラスに許されているメソッドを実行できる。
# using the find method, we grab the "real" david as a User 
david = users(:david).find

# and now we have access to methods only available to a User class 
email(david.girlfriend.email, david.location_tonight) 

3. Unit Testing your Models

まず Test 用の Rails プロジェクト (TestingRails) を作成しておく。


/home/abekatsu/webroot% rails TestingRails
      create  
      create  app/controllers
      create  app/helpers
      create  app/models
      create  app/views/layouts
      create  config/environments
      create  config/initializers
      create  config/locales
      create  db
      create  doc
      create  lib
      create  lib/tasks
      create  log
      create  public/images
      create  public/javascripts
      create  public/stylesheets
      create  script/performance
      create  test/fixtures
      create  test/functional
      create  test/integration
      create  test/performance
      create  test/unit
      create  vendor
      create  vendor/plugins
      create  tmp/sessions
      create  tmp/sockets
      create  tmp/cache
      create  tmp/pids
      create  Rakefile
      create  README
      create  app/controllers/application_controller.rb
      create  app/helpers/application_helper.rb
      create  config/database.yml
      create  config/routes.rb
      create  config/locales/en.yml
      create  config/initializers/backtrace_silencers.rb
      create  config/initializers/inflections.rb
      create  config/initializers/mime_types.rb
      create  config/initializers/new_rails_defaults.rb
      create  config/initializers/session_store.rb
      create  config/environment.rb
      create  config/boot.rb
      create  config/environments/production.rb
      create  config/environments/development.rb
      create  config/environments/test.rb
      create  script/about
      create  script/console
      create  script/dbconsole
      create  script/destroy
      create  script/generate
      create  script/runner
      create  script/server
      create  script/plugin
      create  script/performance/benchmarker
      create  script/performance/profiler
      create  test/test_helper.rb
      create  test/performance/browsing_test.rb
      create  public/404.html
      create  public/422.html
      create  public/500.html
      create  public/index.html
      create  public/favicon.ico
      create  public/robots.txt
      create  public/images/rails.png
      create  public/javascripts/prototype.js
      create  public/javascripts/effects.js
      create  public/javascripts/dragdrop.js
      create  public/javascripts/controls.js
      create  public/javascripts/application.js
      create  doc/README_FOR_APP
      create  log/server.log
      create  log/production.log
      create  log/development.log
      create  log/test.log

Railsにおいて,Unit Testとはモデル(Model)のテストを書くことである。まずは,モデルpostをscaffoldで構築してみて,その際にできるtest suiteについて見てみる。

/home/abekatsu/webroot/TestingRails% script/generate scaffold post test:string body:text
      exists  app/models/
      exists  app/controllers/
      exists  app/helpers/
      create  app/views/posts
      exists  app/views/layouts/
      exists  test/functional/
      exists  test/unit/
      create  test/unit/helpers/
      exists  public/stylesheets/
      create  app/views/posts/index.html.erb
      create  app/views/posts/show.html.erb
      create  app/views/posts/new.html.erb
      create  app/views/posts/edit.html.erb
      create  app/views/layouts/posts.html.erb
      create  public/stylesheets/scaffold.css
      create  app/controllers/posts_controller.rb
      create  test/functional/posts_controller_test.rb
      create  app/helpers/posts_helper.rb
      create  test/unit/helpers/posts_helper_test.rb
       route  map.resources :posts
  dependency  model
      exists    app/models/
      exists    test/unit/
      exists    test/fixtures/
      create    app/models/post.rb
      create    test/unit/post_test.rb
      create    test/fixtures/posts.yml
      create    db/migrate
      create    db/migrate/20090929002133_create_posts.rb

モデルに関するテスト箇所は,

      create    app/models/post.rb
      create    test/unit/post_test.rb
      create    test/fixtures/posts.yml

test/unit/post_test.rbを見てみる。

require 'test_helper'

class PostTest < ActiveSupport::TestCase
  # Replace this with your real tests.
  test "the truth" do
    assert true
  end
end

次の
  test "the truth" do
    assert true
  end
がガイドと違うところ。ActiveSupport::TestCaseを見てもよくわからない。ひとまず,気にしないでおいておく。
テスト用クラスは ActiveSupport::TestCase の 子クラス。テスト内容は

  assert true

のように,trueがtrueであるかないか。だから,かならず成功しなければいけないテストが含んでいる。次節に進んでみる。

3.1 Preparing your Application for Testing

まずDBの構造を最新にしておくために "rake db:migrate" を実行する。


/home/abekatsu/webroot/TestingRails% rake db:migrate
(in /home/abekatsu/webroot/TestingRails)
==  CreatePosts: migrating ====================================================
-- create_table(:posts)
   -> 0.0019s
==  CreatePosts: migrated (0.0021s) ===========================================



"db/scheme.rb" ができていることを確認して,"rake db:test:load" で,テスト用データベースを作成する。いつの時点でも,"rake db:test:load" でテスト用データベースを再構築することができる。
この段階で,"rake db:test:prepare" を実行できる。

/home/abekatsu/webroot/TestingRails% rake db:test:load
(in /home/abekatsu/webroot/TestingRails)
/home/abekatsu/webroot/TestingRails% rake db:test:prepare
(in /home/abekatsu/webroot/TestingRails)

テスト用にアプリケーションを準備するためのRake Tasksはになって示されている。
実際にテストを実行してみる。例では "ruby unit/post_test.rb -n test_truth" と test method を指定しているが,上記ではメソッド "test_truth" を定義していないので "ruby unit/post_test.rb" を実行してみる。

/home/abekatsu/webroot/TestingRails% cd test 
/home/abekatsu/webroot/TestingRails/test% ruby unit/post_test.rb 
Loaded suite unit/post_test
Started
.
Finished in 0.202105 seconds.

1 tests, 1 assertions, 0 failures, 0 errors
/home/abekatsu/webroot/TestingRails/test% 

次に,"タイトルがないポストを保存してはならないテスト(test_should_not_save_post_without_title)" を作成する。"unit/post_test.rb" に次のテストを追加する。
  test "post should not save without title" do
    post = Post.new
    assert !post.save
  end
今のところ,モデルPostはいじっていないので,このテストは必ず失敗するはず。実行してみる。

/home/abekatsu/webroot/TestingRails/test% ruby unit/post_test.rb
Loaded suite unit/post_test
Started
F.
Finished in 0.21082 seconds.

  1) Failure:
test_post_should_not_save_without_title(PostTest) [unit/post_test.rb:11]:
 is not true.

2 tests, 2 assertions, 1 failures, 0 errors

test_post_should_not_save_without_title(PostTest) [unit/post_test.rb:11] が失敗していることを確認した。もうちょっとかっこよくtestを表示させてみたいので,
  test "post should not save without title" do
    post = Post.new
    assert !post.save, "Saved the post without a title"
  end
とassert文に追加して,テスト実行。ちょっとかっこいい。
/home/abekatsu/webroot/TestingRails/test% ruby unit/post_test.rb
Loaded suite unit/post_test
Started
F.
Finished in 0.262242 seconds.

  1) Failure:
test_post_should_not_save_without_title(PostTest) [unit/post_test.rb:11]:
Saved the post without a title.  <== "Saved the post without a title" が表示されている。
 is not true.

2 tests, 2 assertions, 1 failures, 0 errors
/home/abekatsu/webroot/TestingRails/test% 
それでは,このテストが通るように,モデルPostを編集してみる。編集するファイルは "app/models/post.rb"
"app/models/post.rb"を次のように編集する。titleが存在していないと保存できないようにするために "validates_presence_of :title" を追加する。

class Post < ActiveRecord::Base
  validates_presence_of :title
end
"validates_presence_of" は ActiveRecord::Validations::ClassMethodsで定義されているメソッド。引数はsymbol。ここでは "title"。なぜ ActiveRecord::Validations::ClassMethods をここで呼ぶことができるのかがわからない。
再びテストを実行してみる。

/home/abekatsu/webroot/TestingRails/test% ruby unit/post_test.rb
Loaded suite unit/post_test
Started
..
Finished in 0.189441 seconds.

2 tests, 2 assertions, 0 failures, 0 errors
今度はテストが成功したことがわかる。
To see how an error gets reported, here's a test containing an error(うまく日本語に訳せない。)再び "post_test.rb" に戻って,

  test "test sholud report error" do
    some_undefined_variable 
    assert true
  end
を追加して,テストを実行してみる。

/home/abekatsu/webroot/TestingRails/test% ruby unit/post_test.rb             
Loaded suite unit/post_test
Started
.E.
Finished in 0.191917 seconds.

  1) Error:
test_test_sholud_report_error(PostTest):
NameError: undefined local variable or method `some_undefined_variable' for #
    unit/post_test.rb:15:in `test_test_sholud_report_error'

3 tests, 2 assertions, 0 failures, 1 errors
ここまでで 3.2 節。次節はUnit Test

わからないこと

  • なぜ validates_of が ActiveRecord::Base 内で呼ぶことができるのか?
  • "the truth" と書かれたところだけテストを実行してみたいのだが,どのように指定しればいいのかよくわからない。全てのテストはパスさせなければいけないから,そんなことを考えるのは無意味だろうか。

その他

15 TDD steps to create a Rails applicationというのが公開されている。

Saturday, September 19, 2009

前日までのまとめ。

Railsアプリケーションを作ってみよう。せっかくなのでTest Drivenで(あってたっけ)。 とりあえず,ここからなのか。 A Guide to Testing Rails Applications 道外れないように。

Sunday, September 13, 2009

これからどうしよう

SNSに複数加入していたり,blogを複数管理していると,コンテンツ管理が面倒だよね。 - (同じ内容をPostする際の憂鬱さは何ともいえない。) だったら,SNSの日記をblog先にすればいいじゃないか。 - 外のサイトにコメント残すなんて,心理的抵抗感はないのか。mixiから外のblogを参照するのっていやじゃない?そんなことはない? - twitterなんかもでてくると何がなんやら。 それじゃ,コンテンツ管理システムなんて実装してしまうのよくないか? せっかくなので,Railsを使ってやってみよう。 と思い,Railsを触りだす。入力formを作って,Postを実行する時に,mixiやblogに投稿する処理を行えばいいじゃない? (form画面までは作った。) Google Data on Railsを見つけた。www.blogger.com はこれでいい。 じゃ,XMLRPCを喋らすにはどうしよう。Rails2.0からはActionWebServiceじゃなくてActiveResourceにおきかわった。ActiveResourceを使ったサンプルは?まずは Google Data on Railsを触ってみよう。 でもこんなことやってていいのだろうか,技術論が先にでて,お客様へのサービスとは何 かを考えたとき,こんなことやってていいのだろうか,と激しく思う。IPv6やらmobile IPなどなど出てきたけど,service in したか? 今どんなことやっているのか上手く説明できないし,それでお客様は何でよろこぶの,と自問?する。たいして,プログラムが書けるわけじゃない,PCに向かって,今後生きていられるのか激しく悩んでる。自分の進んでいる道間違っていたのだろうかと。 混乱中 (いま,ココ。)

Thursday, August 27, 2009

秋田のカフェでプログラマーの交流会

秋田経済新聞の記事より,秋田のカフェでプログラマーの交流会-地元プログラマーが企画主宰の伊藤勝良さんのブログAkita.m 今回は都合がつかないのですが,次回のチャンスがあれば是非参加したいと思います。 どんな分野のsoftware engineer/programmerが地元にいるのか,交流深めてみたいです。 ところで,私は秋田市を,盛岡市,青森市よりも遠くにあると感じてしまうのでしょう? 鹿角から秋田市に行くのにどれくらいかかるのでしょうかとGoogle mapに頼るとこんなかんじ。
大きな地図で見る これだとあんまりなので,斜めに走るように国道285号線を使えばいいと思うけど,2時間半はかかるな。 青森,盛岡だと100km以内という感覚があるから,150kmってすごく遠い気がします。

Monday, August 10, 2009

Should use temporary IPv6 addresses for Ubuntu user?

(English) I am using Ubuntu 9.04 desktop and I notice that eth0 has an IPv6 address, which is generated from EUI-64 including MAC address. But it raises a privacy issue. Please refer to the followings: I look for the sysctl information and I find the "net.ipv6.conf.all.use_tempaddr" and its value is 0. But it didn't work. It is necessary to set net.ipv6.conf.eth0.use_tempaddr = 1. But I don't find how to disable IPv6 address which is based on EUI-64. Some Internet draft says that this extension could make hard for future defenses against DDoS attacks. I'll be looking for this issue.

Wednesday, July 15, 2009

Android用アプリ AozoraReader

著作権が消滅した作品や,自由に公開されている作品等を揃えておりますインターネット図書館「青空文庫」へのアクセスを簡単にいたしましたAndroid用アプリケーション AozoraReader のβ版を公開いたします。
  • 頻繁かつ大量のパケット通信を行うことがございますので,ご契約の携帯電話の料金プランを今一度確認願います。
  • 作家インデックスから作家,作品を選択いたしまして,手元の画面に表示いたします。
  • 過去10件の履歴を管理し,トップ画面から直接作品にアクセスすることができます。
不十分なところが多々ございますが,お時間がございましたら,お試しいただけたらと思います。

FAQ

Android マーケットには出さないのですか?
非常に日本語に特化したアプリケーションですので,日本語用Androidマーケットが確立された場合に検討させてください。
縦書きへの対応予定は。
現在はWebViewに直接XHTMLファイルを表示させております。独自のLayoutを作ることでで縦書きに対応させたいと考えております。個人的には縦書きや右から左へ表示させるViewが提供できればいいのかと思います。

Feature Plan

  • しおり機能の実装
  • 履歴管理
  • 簡易縦書きレイアウトへの表示
  • アイコンのデザイン
  • TBD
今後とも,他のAndroid向けアプリケーションの公開を続けていきたいと考えております。

Wednesday, June 24, 2009

Monday, June 15, 2009

どう料理すればいいのやら?

あなたの遭遇したバグや不具合の「イケてない回避策」は?
typoがあると,デーモンが死んでしまうという問題があった。それまでのバージョンでは,間違いのある行を無視するとかという対処だったのが。 障害報告をあげると「対策: 書き間違わないでください」という英文FAXが返ってきた。
これを見て,思い出したこと。 インストーラが示すインストール先と実際のインストール先とかが異なっていたこと。 レポートあげたが,仕様といわれた。 設定用アプリケーションにもひどい仕様があった。 探索用パケットのsrc IP addressが適当であった。 (ルールはよくわかんないけど,WSAIoctlとかなんとかで取得したinterfacesの最初の要素を無条件に採用してんじゃないのか?) たまたま有線LANと無線LANのnetworkが違っていた環境だったから気づいたのだけど,こんな状況は特殊なのだろうか。仮想インタフェースあったらアウトだろう。(workaroundは有線以外の全てのインタフェースを無効にする。) 他にも「仕様」の一言で片付けられている状況に腹立たしく思っているのだが, こんな文化があるんだったら逃げるのが正解か? ■[システム開発][Agile開発]もうこういうのやめようよ...masayangの日記(ピスト通勤他 より。
日経SYSTEMS実践セミナー 手戻りなしの要件定義テクニック 手戻りって,そんなにいけないの?ソフトウェアはhardwareじゃなくてsoftwareだから,手戻りもありじゃないのか。それならば全部,ROMに書いて出荷しちゃえよ。あ,今でもそうか。

Monday, March 30, 2009

build androind on Ubuntu intrepid (x86_64)

Android を Ubuntu Intrepid (x86_64) でbuildしようとしても,libz.soが見つからないと怒られる。
host Executable: aapt (out/host/linux-x86/obj/EXECUTABLES/aapt_intermediates/aapt)
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libz.so when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.3.2/../../../libz.a when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/libz.so when searching for -lz
/usr/bin/ld: skipping incompatible /usr/lib/libz.a when searching for -lz
/usr/bin/ld: cannot find -lz
collect2: ld はステータス 1 で終了しました
make: *** [out/host/linux-x86/obj/EXECUTABLES/aapt_intermediates/aapt] エラー 1
Issue 1005のthreadを読むと,getlibsというツールがあって,libz.soはどのパッケージをインストールすればいいのかがわかる。
sakura@/home/abekatsu/src/android% getlibs libz.so
libz.so: zlib1g-dev
The following i386 packages will be installed:
zlib1g-dev<
なので,zlib1g-devをいれてみると,buildが進んだ。

Sunday, March 01, 2009

Configure Static IP address on Ubuntu 8.10 using Network Manager

It's just my reminder. I did not re-test with the following procedure. So Please tell me if you cannot configure static IPv4 address via Network Manager.

Procedures:
  • Open Network Manager.

  • Delete DHCP configuration.
  • Add new connection for wired network configuration.

  • On editing dialog, Add IP address, netmask and gateway. (In most cases, you put the default gateway IP address). And put your resolver below.

  • Sorry, Japanese Characters are used in screen capture images.

    There was an error in this gadget