Rails 3.1: assign_attributesメソッド
2011/05/14
ゴールデンウィーク中の5月5日にRails 3.1 beta1がリリースされました。
派手な点としてはJQuery, CoffeeScript, Sassなどをデフォルトして採用したことが挙げられますが、私が注目しているのはActive Recordに加えられたassign_attributesメソッドです。
その基本的な役割は、昔からあるattributes=メソッドと同じです。たとえば、Userモデルとusersコントローラがあって、users#updateアクションが次のように書かれているとします。
def update
@user = User.find(params[:id])
@user.attributes = params[:user]
if @user.save
redirect_to @user
else
render :edit
end
end
Rails 3.1では、3行目を次のように書くことができます。
@user.assign_attributes(params[:user])
私としては、類似した機能を持つupdate_attributesメソッドと書き方が共通になった点をまず喜びたいのですが、ポイントはそこではありません。
今、Userモデルにnameおよびis_adminという2つのフィールドがあるとします。そして、is_adminフィールドを守るために、app/models/user.rbのソースコードは次のようになっているとします。
class User < ActiveRecord::Base attr_accessible :name end
すると、仮にparams[:user]の中身が { :name => "tsutomu", :is_admin => true } であったとしても、
@user.attributes = params[:user]
と書くだけでは、is_adminフィールドは書き換わりません。明示的に次のように書く必要があります。
@user.attributes = params[:user] @user.is_admin = true
これは、悪意を持ったユーザーが自分のアカウントのis_adminフィールドをtrueにする、という事態を避けるための予防措置です。たとえ編集フォームにis_adminフィールドを切り替えるチェックボックスがなくても、ユーザーは簡単なスクリプトを作ってis_adminフィールドを含むパラメータをPOSTすることができるからです。
さて、usersコントローラとは別にadmin/usersコントローラがあるとします。こちらのコントローラにアクセスできるのが管理者だけだとすれば、今述べたような予防措置は不要です。
ここで登場するのが、assign_attributesメソッドです。
まず、app/models/user.rbを次のように書き換えます。
class User < ActiveRecord::Base attr_accessible :name attr_accessible :name, :is_admin, :as => :admin end
attr_accessibleメソッドのオプション:asは、Rails 3.1で登場したものです。で、admin/users#updateアクションはこうなります。
def update
@user = User.find(params[:id])
@user.assign_attributes(params[:user], :as => :admin)
if @user.save
redirect_to @user
else
render :edit
end
end
いかがでしょうか? 感動するかどうかは人それぞれでしょうが、少なくとも私は心の中で「ブラーヴォ」とつぶやいてしまいました。こういう類の渋い改善点をコンスタントに追加してくるところが、Railsコミュニティのすごいところです。
