おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

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になる。いよいよルーティングを定義する必要があるみたい。続きはまた今度にしよう。