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 も必要。無論、ruby の mysql ライブラリ (debian では libmysql-ruby パケジ) も必要。debian 的には上記パケジが最低限あれば rails は動く。
DB の設定
DB が別ホストの場合、サーバ側で最低でも以下の処理が必要。
migrate
model の生成時に migrate なナニも作成されるので、手順としては model の generate 後に db/migrate/ 以下のナニを作成して rake migrate 実行、となる。
ajax なナニを例に取ると (DB の作成と接続確認がデキている事が前提)
- model の generate
- 生成された migrate なナニを edit
- 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 を以下に。
- http://wota.jp/ac/?date=20050808#p01
- http://www.asahi-net.or.jp/%7Esd5a-ucd/rec-html401j/present/styles.html#h-14.3
- http://wota.jp/ac/?date=20050721#p01
AWDwR の chapter.17.9 は熟読が必要 (って理解できるのだろうか)。
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 としては変わりない?