ajax なアプリ

情報誌の記事なのに写経って微妙だな。ってか限りなくアウトだ。著作権者な方に無断でナニしてるんで写経なコード部分については削除する予定。セーフな控えを残しておきたい、と。
# 確かに、やってみました + そのコードを引用、では log 以前のアレかも。(恥

debootstrap 使って環境構築なナニ

debootstrap 使って環境構築な手順を以下に。

# debootstrap sarge /test-root http://ring.hosei.ac.jp/archives/linux/debian/debian/
# echo "proc /test-root/proc proc none 0 0" >> /etc/fstab
# mount proc /test-root/proc -t proc
# cp /etc/hosts /test-root/etc/hosts
# chroot /test-root /bin/bash
/# vi /etc/apt/sources.list
(sarge から testing へ sources.list 修正)
/# aptitude dist-upgrade -fy
/# cd /dev
/dev# /sbin/MAKEDEV generic
/dev# aptitude install locales mtools -fy
/dev# cd /
/# useradd -m guest
/# passwd guest
/# aptitude install -fy mysql-client ruby rake libmysql-ruby irb

DB (この例では mysql) は別な環境で稼働させているものとして、chroot なナニには client のみをインストール。で、rails の試験を行なうためには、ruby は勿論の事、rake や irb も必要。無論、rubymysql ライブラリ (debian では libmysql-ruby パケジ) も必要。debian 的には上記パケジが最低限あれば rails は動く。

DB の設定

DB が別ホストの場合、サーバ側で最低でも以下の処理が必要。

  • my.cnf の設定
    debian では bind-address が 127.0.0.1 となっている。別ホストから接続するケースでは、これをコメントアウトする等の措置が必要。ちなみに複数の IP アドレスを指定することは不可能との事にて、コメントアウトするしかないカンジ。
  • create database
    default character set utf8 を付けるのは rails 標準かも。
  • grant
    適切な grant は必要。

migrate

model の生成時に migrate なナニも作成されるので、手順としては model の generate 後に db/migrate/ 以下のナニを作成して rake migrate 実行、となる。

ajax なナニを例に取ると (DB の作成と接続確認がデキている事が前提)

  1. model の generate
  2. 生成された migrate なナニを edit
  3. rake migrate の実行

実例を以下に。

list と item model を生成。

$ script/generate model list
     exists  app/models/
     exists  test/unit/
     exists  test/fixtures/
     create  app/models/list.rb
     create  test/unit/list_test.rb
     create  test/fixtures/lists.yml
     create  db/migrate
     create  db/migrate/001_create_lists.rb
$ script/generate model item
     exists  app/models/
     exists  test/unit/
     exists  test/fixtures/
     create  app/models/item.rb
     create  test/unit/item_test.rb
     create  test/fixtures/items.yml
     exists  db/migrate
     create  db/migrate/002_create_items.rb
$

まず、migrate を修正。

db/migrate/001_create_lists.rb

 def self.up
   create_table :lists do |t|
     # t.column :name, :string
     t.column :title, :string
     t.column :created_on, :time
     t.column :updated_on, :time
   end
 end

 def self.down
   drop_table :lists
 end
end

db/migrate/002_create_items.rb

class CreateItems < ActiveRecord::Migration
 def self.up
   create_table :items do |t|
     # t.column :name, :string
     t.column :list_id, :integer
     t.column :note, :string
     t.column :completion, :boolean, :default => false
     t.column :position, :int
     t.column :created_on, :time
     t.column :updated_on, :time
   end
 end

 def self.down
   drop_table :items
 end
end

で、migrate。

$ rake migrate
(in /home/guest/todo)
== CreateLists: migrating =====================================================
-- create_table(:lists)
  -> 0.7665s
== CreateLists: migrated (0.7668s) ============================================

== CreateItems: migrating =====================================================
-- create_table(:items)
  -> 0.1126s
== CreateItems: migrated (0.1130s) ============================================

$

処理結果を確認。

$ mysql -u xxx todo -p -h 192.168.0.1
Enter password:
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 14 to server version: 5.0.22-Debian_2bpo1-log

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> show tables ;
+----------------+
| Tables_in_todo |
+----------------+
| items          |
| lists          |
| schema_info    |
+----------------+
3 rows in set (0.00 sec)

mysql> desc items ;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| list_id    | int(11)      | YES  |     | NULL    |                |
| note       | varchar(255) | YES  |     | NULL    |                |
| completion | tinyint(1)   | YES  |     | 0       |                |
| position   | int(11)      | YES  |     | NULL    |                |
| created_on | time         | YES  |     | NULL    |                |
| updated_on | time         | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
7 rows in set (0.01 sec)

mysql> desc lists ;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255) | YES  |     | NULL    |                |
| created_on | time         | YES  |     | NULL    |                |
| updated_on | time         | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> \q
Bye
$

model の実装について

まず、list と item の関係は_1 対多_となるので、
List は item をたくさん持ち (has_many items)

Item は list に属する (belong to)
となる。
で、has_many に見たコトないナニがある。

has_many :items, :order => 'position', :dependent => true

意味的には以下のようなモノになる模様。

List は多くの items を持つ事ができ、その並びは items.position の順 (昇順) で親 (List)
が削除されたら、子 (items) も同時に削除される (:dependent (子は親に従属している) による)。

又、set_field_names は validation なメセジに対応しているはずだな (別途検証が必要)。

あと、act_as_list というナニが item にて指定されているがこれは何か、というと ActiveRecord の機能の一つのようです (AWDwR Chapter.15 にも出てた)。position てのはキメの列名のようですな。ただ、AWDwR では列名がシンボルとして与えられておりますが、上記の例では id が略されてるのか、はたまたバージョンが新しいゆえのナニなのかは不明
(できれば別途調査)。

これも別途になると思いますが、UT のナニも残しておきたい。

controller および view について

まずは ERB なナニについて

  • stylesheet_link_tag
    public/stylesheets/ 配下の指定されたスタイルシートを読み込む (上記の例であれば public/stylesheets/style.css を読み込む)。
  • javascript_include_tag
    public/javascripts/ 配下の指定されたソースを読み込む (上記の例であれば public/javascripts/prototype.js と public/javascripts/scriptaculous.js を読み込む)。
  • @content_for_layout
    render の結果と置き換えられる、との事らしいが、このケースの場合 (まだソース作成してませんが) は以下のような順で処理が行なわれると類推できる。(検証未完)
    • ブラウザから task/index の要求
    • TaskController の index action 実行
    • index view のスクリプトな部分の展開
    • tasklists な id の部分については、_list.rhtml を使用して展開
    • 展開された index view が TaskContrller で指定されている default.rhtml の@content_for_layout と置換
    • ブラウザに展開された html を送信

参考 URL を以下に。

Controller についての気付きを以下に。
まず、http://wota.jp/ac/?date=20050720#p01 によると、「コントローラ内でCGIのリクエスト・レスポンスに対する前処理・後処理を行うのが Filter 機能です。(Filtersより引用)」とある。before_filter により charset の指定をしてるんですが、これはブラウザから受け取った文字コードの指定だと考えて良いのでしょうか。
又、layout という指定は引用符で囲んだ場合、app/views/layouts/ 固定でこの例であれば、app/views/layouts/default.rhtml が指定された、という意味となる。

task アクションの index ビューについては再度引用させて頂きます。ポイント高いんで。

app/views/task/index.rhtml

<%= form_remote_tag :url => {:controller => 'ajax', :action => 'add_list'},
       :failure => 'alert(request.responseText)',
       :update => { :success => 'tasklists' },
       :position => :bottom,
       :html => { :class => 'add_list' }
%>
<%= text_field_tag 'title' %>
<%= submit_tag '追加する' %>
<%= end_form_tag %>
<div id='tasklists'>
<%= render :partial => 'list', :collection => @lists %>
</div>

以下、別途調査ってコトで (こら) 根拠のない類推ベースなナニを列挙。

  • form_remote_tag は XMLHttpRequest を使ってフォームのデータの送信を行う。それぞれの引数の意味は以下のようなカンジ。
    • :url は submit 時に実行するアクションを指定。
    • :failure は request 送信後に戻ってきたステイタスが 2xx 又は 3xx 以外の場合の処理を記述
    • :update には DOM エレメントの id 属性を指定する、という記述があるが、:success というシンボルについては不明。上記では tasklists という id な部分が更新される、という意味になる。
    • :position は更新時にどこに追加されるか、という意味。ここでは tasklists という id の末端に追加、となる。
    • :html は意味不明。rails の ML 探してみたが微妙。とりあえず、html に変換されたソースを見てどのように変換されているか、を確認予定。
  • text_field_tag で指定された名前 (上記の例では、title となっている) はアクションに渡される時に params で参照するシンボルとなる。
  • submit_tag は submit ボタンのラベル

で、tasklists という id 属性が付けられた (日本語変) 部分については、_list.rhtml に @lists の要素が展開されて単数形で参照可能となっている模様。このあたりは慣れないと微妙かもしれない。

ajax コントローラの add_list アクションと _list.rhtml については略。以下に TODO を列挙。

  • list.rb から set_field_names の記述をコメントアウトしてエラーメセジを確認
  • acts_as_list の確認 (AWDwR の Chap.15)
  • acts_as_list の引数について調査
  • model の unit test について動作確認し、マトメ作成
  • @content_for_layout なナニについて根拠の検証
  • AWDwR の Chap.17.9 読み
  • before_filter における @headers 設定の意味
  • form_remote_tag について調査
  • text_field_tag、submit_tag について調査
  • render に渡される :collection の展開なナニについて調査
  • render の引数、:text やら :status について調査
  • render メソドの実装について rails のソースを確認
  • controller および view の unit test についての動作確認必要。ajax なナニが入っていても UT としては変わりない?