是非に及ばず

プログラミングに関する話題などを書いていきます(主にRailsやAndroidアプリ開発について)

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