その他
    ホーム技術発信DoRubyresource_controller で RESTful, DRY 実践

    resource_controller で RESTful, DRY 実践

    この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

    Rails 2.0 からの RESTful 指向により、ほとんどのコントローラは index, show, new, create, edit, update, destroy の基本的なアクションを持ちます。
    コントローラはモデルとビューの中継ぎをするためのコードを持ち、ビジネスロジックはモデルに持つという思想を実践すれば、コントローラのコードはほとんど同じコードになります。
    このコントローラの状況は、Rails の DRY (Don’t Repeat Yourself)の法則に反することになります。
    そこで今回紹介する resource_controller の出番です。

    script/generate scaffold post で作成したコントローラは以下のようになります。

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml
      def index
        @posts = Post.find(:all)
    
        respond_to do |format|
          format.html # index.html.erb
          format.xml  { render :xml => @posts }
        end
      end
    
      # GET /posts/1
      # GET /posts/1.xml
      def show
        @post = Post.find(params[:id])
    
        respond_to do |format|
          format.html # show.html.erb
          format.xml  { render :xml => @post }
        end
      end
    
      # GET /posts/new
      # GET /posts/new.xml
      def new
        @post = Post.new
    
        respond_to do |format|
          format.html # new.html.erb
          format.xml  { render :xml => @post }
        end
      end
    
      # GET /posts/1/edit
      def edit
        @post = Post.find(params[:id])
      end
    
      # POST /posts
      # POST /posts.xml
      def create
        @post = Post.new(params[:post])
    
        respond_to do |format|
          if @post.save
            flash[:notice] = 'Post was successfully created.'
            format.html { redirect_to(@post) }
            format.xml  { render :xml => @post, :status => :created, :location => @post }
          else
            format.html { render :action => "new" }
            format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
          end
        end
      end
    
      # PUT /posts/1
      # PUT /posts/1.xml
      def update
        @post = Post.find(params[:id])
    
        respond_to do |format|
          if @post.update_attributes(params[:post])
            flash[:notice] = 'Post was successfully updated.'
            format.html { redirect_to(@post) }
            format.xml  { head :ok }
          else
            format.html { render :action => "edit" }
            format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
          end
        end
      end
    
      # DELETE /posts/1
      # DELETE /posts/1.xml
      def destroy
        @post = Post.find(params[:id])
        @post.destroy
    
        respond_to do |format|
          format.html { redirect_to(posts_url) }
          format.xml  { head :ok }
        end
      end
    end
    

    resource_controller を使えば、上記のコードは次の様になります。

    class PostsController < ApplicationController
      resource_controller
    end
    

    また、/post/1/comments の様なネストしたコントローラにも対応しています。

    class CommentsController < ApplicationController
      resource_controller
      belongs_to :post
    end
    

    belongs_to を使えば、/post/1/comments の様な URL で Comments コントローラにアクセスした場合に、自動的に @post インスタンス変数に親オブジェクトを生成してくれたりします。

    resource_controller プラグインをインストールするには以下のコマンドを実行します。

    script/plugin install git://github.com/giraffesoft/resource_controller.git
    

    こちらのブログでさらに詳細が書かれていますので、興味ある人はご覧下さい。
    resource_controller で RESTful, DRY な生活を送りましょう!