Posted at

Railsでactiveadmin使用時にto_paramをid以外にしていた場合の対処法

activeadminはとても便利ですね!

簡単に管理画面を作成できるだけでなく、ある程度のカスタマイズにも対応できます。


何をしたいか :thinking:

Railsではmodelにto_paramというメソッドがあり、これを上書きすることでURLに含まれる:idを他のカラムにすることができます。

例えば以下のようにすることで、/events/:id/のidをnameカラムにすることできます。

class Events < ApplicationRecord

def to_param
name
end

end

to_paramの上書きはしばしばやると思うのですが、activeadminでの対応方法がネットで見つけづらかったので、記事にしようと思います。


何が起こるか :cry:

上記のようにto_paramを上書きした場合activeadminではどうなるのでしょうか?

activeadminは今のモデル構造を分析することで自動的に管理画面を作成できるようになっています。そのためto_paramもしっかり認識してくれます。

しかし、上書きした状態でactiveadminで詳細画面や編集画面を見ようとするとエラーしてしまいます。

スクリーンショット 2018-10-25 19.34.35.png

これは、admin/eventsに表示される「閲覧・編集・削除」などのリンクがto_paramによってadmin/events/:name/となっているものの、内部のfindwhereではidで検索していることに起因しています。


解決法 :hammer_pick:

ActiveAdmin.registerのファイルに少しオプションを書くだけで対応できます。

ActiveAdmin.register Event do

# ここから
controller do
def find_resource
scoped_collection.where(name: params[:id]).first!
end
end
# ここまで
end

読んでいるだけで理解できそうです。

通常where(id: params[:id])となるところをwhere(name: params[:id])にするだけです。


注意点 :warning:

公式には以下のような文言で注意点が書かれています。

Note that if you use an authorization library like CanCan, you should be careful

to not write code like this, otherwise **your authorization rules won't be
applied**:

```ruby
ActiveAdmin.register Post do
controller do
def find_resource
Post.where(id: params[:id]).first!
end
end
end

これはつまり、モデル名ではなく、scoped_collectionを使わないとadminの権限管理が機能が効かないよ。ということですね。みなさんも注意してください!