Rails で ActiveRecord クエリをフィルタリングする 質問する

Rails で ActiveRecord クエリをフィルタリングする 質問する

私は、クエリセットに対して複数のフィルター メソッドを実行できる Django に慣れていますItem.all.filter(foo="bar").filter(something="else")

ただし、Rails でこれを行うのはそれほど簡単ではありません。Item.find(:all, :conditions => ["foo = :foo", { :foo = bar }])配列を返すため、これは機能しません。

Item.find(:all, :conditions => ["foo = :foo", { :foo = 'bar' }]).find(:all, :conditions => ["something = :something", { :something = 'else' }])

そこで、フィルターを「スタック」する最良の方法は、条件配列を変更してからクエリを実行することだと考えました。

そこで私は次のような関数を思いつきました:

 def combine(array1,array2)
   conditions = []
   conditions[0] = (array1[0]+" AND "+array2[0]).to_s
   conditions[1] = {}
   conditions[1].merge!(array1[1])
   conditions[1].merge!(array2[1])
   return conditions
 end

使用法:

配列1 = ["foo = :foo", { :foo = 'bar' }] 配列2 = ["something = :something", { :something = 'else' }] 条件 = combine(配列1,配列2) 項目 = Item.find(:all, :conditions => 条件)

これはかなりうまくいきました。ただし、任意の数の配列を結合できるようにしたい、つまり基本的に次のように記述する省略形にしたいのです。

conditions = combine(combine(array1,array2),array3)

誰かこれについて助けてくれませんか? よろしくお願いします。

ベストアンサー1

必要なのは名前付きスコープです:

class Item < ActiveRecord::Base
  named_scope :by_author, lambda {|author| {:conditions => {:author_id => author.id}}}
  named_scope :since, lambda {|timestamp| {:conditions => {:created_at => (timestamp .. Time.now.utc)}}}
  named_scope :archived, :conditions => "archived_at IS NOT NULL"
  named_scope :active, :conditions => {:archived_at => nil}
end

コントローラーでは、次のように使用します。

class ItemsController < ApplicationController
  def index
    @items = Item.by_author(current_user).since(2.weeks.ago)
    @items = params[:archived] == "1" ? @items.archived : @items.active
  end
end

返されるオブジェクトはプロキシであり、反復処理 (表示用) やプロキシで Enumerable メソッドを呼び出すなど、コレクションに対して実際に何か操作を開始するまで、SQL クエリは実行されません。

おすすめ記事