2009-06-01 6 views
21

私はDjangoでクエリセットで複数のフィルタメソッドを実行することができます。つまりItem.all.filter(foo="bar").filter(something="else")です。レールでActiveRecordクエリをフィルタリングする

ただし、これは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 = 'バー'}] 配列2 = [ "何か=:something "、{:something = 'else'}] 条件=結合(配列1、配列2) items = item.find(:all、:conditions =>条件)

これはかなりうまくいっています。しかし、私は任意の数の配列を組み合わせることができる、または基本的に書くための略記:

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

誰でも助けてもらえますか?前もって感謝します。

答えて

35

iterating(表示用)や、Enumerableメソッドをプロキシで呼び出すときなど、コレクションで何かを実際にやりはじめます。

+0

それはまさに私が欲しいものです。私はスクリーンキャストを見て、それは私には完全に意味がありました。しかし、私がコードを起動するとすぐに、名前付きスコープが定義されていないメソッドであるというエラーが出ました。それから、私はRails 1.8で作業していたことに気づいたので、私は2.3レールに更新しましたが、同じエラーが出ました.... ugh、名前付きスコープが本当に良いと分かっていました:/ – user94154

+1

Railsを凍結した場合、あなたのコードはまだ以前のバージョンのRailsを使用しています。 Rails 1.8は決して存在しなかったので、Ruby 1.8を意味する必要があります。 rails -vはコマンドラインに存在するRailsのバージョンを知らせるコマンドです。 script/aboutはアプリケーションの環境について詳しく説明します。 –

+0

ruby​​スクリプト/約が認識されませんでした。 Railsに関してフリーズはどういう意味ですか? – user94154

1

Searchlogicをご覧ください。
ActiveRecordセットの条件、さらにはArraysの条件を使用する方が簡単です。

希望します。

4

私が何をしたいことは、このだと思う:Named Scope

1

することができます(または少なくともすることができるように使用される)Railsの中でとても状のフィルタ:

find(:all, :conditions => { :foo => 'foo', :bar => 'bar' }) 

:fooと:バーフィールドですアクティブなレコードの名前。あなたがする必要があるのは、field_name => valueのペアのハッシュを渡すことだけです。

+0

これは私のために働いた(私は1.8です。7) – John

6

提案したようにはしません。

配列を返し見つけるので、あなたは一例で、それをフィルタリングするために、配列のメソッドを使用することができます。

Item.find(:all).select {|i| i.foo == bar }.select {|i| i.whatever > 23 }... 

また、あなたが名前のスコープで欲しいものachiveことができます。お使いのコントローラで

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 

、次のように使用します:返されたオブジェクトは、プロキシで、SQLクエリは実際にあなたまで実行されません

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 

スコープ命名されている何がしたい

+1

名前付きスコープはこれを実行するよりはるかに優れた方法であり、使用できるチェーン化可能なメソッドを簡単に再利用できます。 – nitecoder

+1

@railsninja:同意しますが、使用する前に名前付きスコープを定義する必要があります。何かを一度だけやりたいのであれば、selectを使う方が簡単です。 – klew

+2

すばやく匿名スコープを作成することができます:http://railscasts.com/episodes/112-anonymous-scopes –

関連する問題