named_scopeでオブジェクトを基点として検索をする
「オブジェクトを基点に検索するといい事があるよ」という事を聞いたので、メモしておく。
前提
- ログイン中のユーザが投稿した記事一覧を表示したいとする。
- URLは/articlesで、ArticlesControllerのindexアクションが呼ばれるものとする
- login_userでログイン中のUserオブジェクトが取得できるものとする
- 認証処理は既にされているものとする
- モデルの定義は以下
-- app/models/user.rb -- class User < ActiveRecord::Base has_many :articles end -- app/models/article.rb -- class User < ActiveRecord::Base belongs_to :user end
ダメな例
class ArticlesController < ApplicationController def index @articles = Article.scoped_by_user_id(login_user.id).paginate(:all, :per_page => 10, :page => params[:page]) end end
または
class ArticlesController < ApplicationController def index @articles = Article.paginate(:all, :conditions => ['user_id = ?', login_user.id], :per_page => 10, :page => params[:page]) end end
この方法では、ログイン中のユーザの持っている情報を表示するコントローラが
増えていくと、login_user.idを条件につけ忘れる可能性が高くなる。
良い例
class ArticlesController < ApplicationController def index @articles = login_user.articles.paginate(:all, :per_page => 10, :page => params[:page]) end end
この方法では、ログイン中のユーザを基点にして検索を行うのでlogin_user.idを付け忘れる事はなくなる。
なお、1対1の時(has_one)のときはlogin_user.article.find()とは出来ないので注意。
その場合は、こうして取得してその値がnilかどうかで処理を分ければいい。
@article = login_user.article