Wavesを試してみる - Model編
引き続きWavesを試してみます。
チュートリアルによると、entryに1:nでcommentモデルとの関連付けをしています。
まずはCommentsテーブルのmigrationを作成します。
rake schema:migration name=add_comments
で、schema/migrations/002_add_comments.rbを編集。
class AddComments < Sequel::Migration
def up
create_table :comments do
primary_key :id
foreign_key :entry_id, :table => :entries
text :name
text :email
text :content
timestamp :created_on
end
end
def down
drop_table :comments
end
end
そういえば、RailsではDBレベルでforeign_keyをあまりつけてないな。あと、created_onはSequelによって自動的に時刻が入るよう。Railsでいうcreated_atだね。created_onだと日付しか入らないみたいな感じがしてしまうのは、Railsの使いすぎか。ちなみにSequelというのはORMです。
migrateをかましたら、Entryモデルを作成します。ていうか、今まで存在しなかったのかよ。デフォルトの動作がWavesの中で定義されていて、それ以外のことをやりたくなったときにはじめてコードを書くのかな。
rake generate:model name=entry
で、models/entry.rbが作成される。
module Blog
module Models
class Entry < Sequel::Model(:entries)
before_save do
set(:updated_on => Time.now) if columns.include? :updated_on
end
end
end
end
before_saveはRailsと一緒かな。テーブルがupdated_onを持っていたら更新してくれるみたい。created_onはSequelでやってくれるのに、updated_onは自前でやるのか。中途半端だなあ。Wavesが勝手にコード吐いてくれるけど。
で、models/default.rbの中身がこれと一緒になっている。明示的にモデルを作成しなかったときは、default.rbが使われるんだな。たぶん。
さて、models/entry.rbにcommentmモデルとの関連付けを定義しましょう。
one_to_many :comments, :from => Blog::Models::Comment, :key => :entry_id
こいつをbefore_saveの下に追加します。Railsでいうところのhas_manyと一緒だね。相手のモデルと参照キーを指定してやんないといけない。fromって、なんだかぼくの認識だと参照先みたいな感じがしてしまう。
つづいてcommentモデルを作成する。
rake generate:model name=comment
models/comment.rbは
module Blog
module Models
class Comment < Sequel::Model(:comments)
before_save do
set(:updated_on => Time.now) if columns.include? :updated_on
end
one_to_one :entry, :from => Blog::Models::Entry
end
end
end
one_to_oneはRailsでいうbelongs_toだな。ここでのfromは違和感がない。
さて、viewのほうにコメントを追加してみます。チュートリアルからちょっとアレンジしてみます。templates/entry/show.mabは
layout :default, :title => @entry.title do
a "すべて見る", :href => '/entries'
h1 @entry.title
textile @entry.content
h2 "コメント"
view :comment, :add, :entry => @entry
view :comment, :list, :comments => @entry.comments
end
こんな感じ。見てわかるように、@entry.commentsみたいな感じでAR的にリレーション先へアクセスできるようです。
さて、add.mabとlist.mabをtemplates/commentディレクトリ下に作ります。
templates/comment/add.mab
form :action => "/comments", :method => 'POST' do
input :type => :hidden, :name => 'comment.entry_id', :value => @entry.id
label "名前"; br
input :type => :text, :name => 'comment.name'; br
label "Email"; br
input :type => :text, :name => 'comment.email'; br
label "コメント"; br
textarea :name => 'comment.content', :rows => 10, :cols => 80; br
input :type => :submit, :value => "書き込み"
end
POST先のURLが/commentsになっている。RailsみたいなURL(/entries/:id/comments)じゃないね。かわりに、hidden fieldを持っていて、そこにentry_idを入れている。これだと、URLはシンプルになっていいかも。REST的にはRailsの方が正しい気もするんだけど。
それから、templates/comment/list.mab
@comments.sort_by( &:created_on ).each do |comment|
name = ((comment.name.nil? or comment.name.empty?) ? "通りすがり" : comment.name)
p %Q|#{name} #{comment.created_on.strftime("%Y-%m-%d %H:%M")}|
textile comment.content
end
チュートリアルのコードはわかりにくくて好きじゃない感じだったので書き直してみました。
で、実際にコメントを書いてみると、/comment//editorなんていうURLに飛ばされるのだけど、当然404になる。いよいよルーティングを定義する必要があるみたい。続きはまた今度にしよう。