質問

たとえば、「Mi」などの特定の name 文字列で始まる名前のユーザーを検索できるフォームがあるとします。 "マイク"および「ミゲル」。私はおそらく次のような検索ステートメントを作成します:

find(:all, :conditions => ['name LIKE ?', "#{name}%"])

フォームに2つのオプションフィールド hair_color eye_color があり、これらを使用して結果をさらにフィルタリングできるとします。クエリの名前部分を無視すると、任意の数のオプションパラメータを受け取ることができる人の検索ステートメントは次のようになります。

find(:all、:conditions => {params [:person]})

2つのオプションパラメータのうち、これと同等の動作をするものはどれですか:

find(:all、:conditions => {:hair_color => hair_color、:eye_color => eye_color})

私が理解できないのは、これらの2種類のクエリをマージする方法です。 「like」に適用されます上記の条件、およびオプションの hair_color および eye_color パラメーター(およびその他のパラメーター)を追加して、結果をさらにフィルター処理できます。

確かにこれを行うためにクエリ文字列を作成できますが、「レールの方法」が必要だと感じています。それはよりエレガントです。必須のバインドパラメーターをオプションのパラメーターとマージするにはどうすればよいですか?

役に立ちましたか?

解決

これは、名前付きスコープの完全な使用法です。

モデルに名前付きスコープを作成します:

named_scope :with_name_like, lambda {|name|
  {:conditions => ['name LIKE ?', "#{name}%"]}
}

この時点で電話をかけることができます

Model.with_name_like("Mi").find(:all, :conditions => params[:person])

そしてRailsはクエリをマージします。

編集:Waseemのコード:

名前がオプションの場合、if条件を使用してメソッドチェーンから名前付きスコープを省略することができます。

unless name.blank?
   Model.with_name_like("Mi").find(:all, :conditions => params[:person])
else
   Model.find(:all, :conditions => params[:person])
end

または名前付きスコープを再定義して同じことを行うこともできます。

named_scope :with_name_like, lambda {|name|
  if name.blank?
    {}
  else
    {:conditions => ['name LIKE ?', "#{name}%"]}
  end
}

更新

最後のコードスニペットのRails 3バージョンは次のとおりです。

scope :with_name_like, lambda {|name|
  if not name.blank?
    where('name LIKE ?', "#{name}%")
  end
}

他のヒント

Waseemリクエストにも準拠しますが、代わりに空白を許可しますか? (" @things = Thing.named_like(params [:name])"を直接使用したい場合には、これはおかしいです)

named_scope :named_like, lambda do |*args| 
  if (name=args.first)
    {:conditions => ["name like ?",name]}
  else
    {}
  end
end

# or oneliner version:

named_scope :named_like, lambda{|*args| (name=args.first ? {:conditions => ["name like ?",name]} : {}) } }

お役に立てばと思います

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top