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コミュニティのすごいところです。