読者です 読者をやめる 読者になる 読者になる

黒魔法使いの弟子

Ruby & Javascript & Hack

Actionは5行まで(入門編)

Rails ruby 入門

ruby1.9で有名なyuguiさんが、以前、以下のようなことをつぶやいております。

actionは5行まで。defとendを含めて7行まで。

Twitter / yugui : @akasata actionは5行まで。defとe ...


MVC関連の話として、Cは薄くMを厚く、という類の話ですね。


では、どうやってControllerのactionを短くすれば良いのか、
Controller側でできる基本的なことを書いてみます(Model側は今度いつかきっとそのうち)。

方針

Controller側でできる努力のひとつとしては、
パラメータ絡みの検証をなるたけActionから省くことがあげられます。


ひとつひとつのActionで個別のパラメータに対して、
if ~ else ~ endを多用しない、ということですね。


では、そのために必要な方法を考えていきます。

verifyでがんばる

簡単な条件を検証する場合、verifyを使います。


例えば、ユーザ作成を行う場合、
ユーザ名とパスワードに値が入っているかどうかを確認する必要があります。


これをAction内でやるのではなく、verifyとして、外側に出します。

class LoginsController < ApplicationController 
  verify :params => [:username, :password],
    :render => {:action => "new"},
    :add_flash => {
      :error => "Username and password required to log in"  
    },
    :only => :create

  def create
    @user = User.authenticate(params[:username], params[:password])
    if @user
      flash[:notice] = "You're logged in"
      redirect_to root_url
    else
      render :action => "new"
    end
  end
end 

あーでも5行超えてますね。残念。

filterでがんばる

verifyよりも複雑な場合は、filterを使います。
以下では、before_filterを使った例を書いてみます。


よくありがちな、このような場合、before_filterですっきりひとつにまとめます。

class PostsController < ApplicationController
  # ... 
  def show
    @post = Post.find(params[:id]) 
  # ... 
  end
 
  def edit
    @post = Post.find(params[:id]) 
  end 

  def update
    @post = Post.find(params[:id]) 
  # ... 
  end 

  def destroy
    @post = Post.find(params[:id]) 
  # ... 
  end
end 


before_filterでスッキリ。

class PostsController < ApplicationController
  before_filter :find_post,
    :only => [:show, :edit, :update, :destroy]

  # ... 
  def show
  # ... 
  end 

  def edit
  end 

  def update
  # ... 
  end 

  def destroy
  # ...
  end

  private 

    def find_post
      @post = Post.find(params[:id]) 
    end
end 

おわりに

こんなカンジで、Actionの贅肉をそぎ落としていきましょう。
あと、つっこみ歓迎です。


また、verifyやfilterの各種パラメータの翻訳が欲しいひとは、
ダントツオススメのこちらの本を買いましょう。

Rails3レシピブック 190の技

Rails3レシピブック 190の技


p.66あたりから詳しく書いてあります。