scaffold_resourceでRESTfullなRailsアプリ(2)

scaffold_resourceを試してみる第2段、下のサイトを参考にしてhas_manyな場合を試してみる。
Web 2.0 Technologies: Nested CRUD resources in Rails 1.2

まずscaffoldを作る。post->commentsなhas_manyの関係のモデルの場合

ruby script/generate scaffold_resource Post title:string body:text
ruby script/generate scaffold_resource Comment body:text

/db/migrate/002_create_comments.rb へ外部キーを追加、あとhas_many/belongs_toをモデルへ追加

t.column :post_id, :integer

class Post < ActiveRecord::Base
  has_many :comments
  
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

/config/routes.rbにmap.resourcesが入っているので修正してhas_manyの構造に

ActionController::Routing::Routes.draw do |map|
  map.resources :posts do |posts|
    posts.resources :comments
  end
  map.connect ':controller/service.wsdl', :action => 'wsdl'
  map.connect ':controller/:action/:id.:format'
  map.connect ':controller/:action/:id'
end

あとは細かい部分を修正。

  • 使いやすくするために、before_filterで親のpostを@postとして持っておく
  • commentsのindex表示を@post.comments.find(:all)に変更
  • comment新規作成時にpost_idを保存
  • comment関連Viewのリンクを<%= link_to 'Show', comment_path(@post, @comment) %>みたいに変更
このあたりは今までのRailsアプリと同じ感覚だと思う

class CommentsController < ApplicationControlle
  before_filter (:get_post)
  def index
    @comments = @post.comments.find(:all)
    respond_to do |format|
      format.html # index.rhtml
      format.xml  { render :xml => @comments.to_xml }
    end
  end
  def create
    @comment = Comment.new(params[:comment])
    @comment.post_id = @post.id
    ...........
  end
  ............
  private
  def get_post
    @post = Post.find(params[:post_id])
  end
end

で、アクセスしてみる

GET /posts/1               #id=1のpostを表示
GET /posts/1/comments      #id=1のpostに紐づくcomment一覧
POST /posts/1/comments     #id=1のpostに紐づくcomment新規作成
PUT  /posts/1/comments/1   #id=1のpostに紐づくcommentの更新
DELETE /posts/1/comments/1 #id=1のpostに紐づくcommentの削除

疑問:postのID=1が params[:post_id]に入ってくるのはなんで?map.resources{|post| post.resources}のおかげ?