0

ユーザーがさまざまな種類の組み合わせを使用してさまざまな方法でフィルタリングできるテーブルがあります。ユーザーから取得するすべての入力データを使用して、SQLからユーザーデータをエスケープすることが重要でした。これにより、現在発生している問題が発生します。アクションに送信されたパラメータに基づいて動的に構築される2つの配列があります。1つの配列にはSQL句が含まれ、もう1つの配列にはそれぞれの計算とペアになる値が含まれます...たとえば...

def results

  sql_clauses = Array.new
  sql_args = Array.new

  unless params[:elapsed_time].nil?
    sql_clauses << "elapsed_time = ?"
    sql_args << params[:elaped_time] 
  end
  unless params[:age_greater_than].nil?
    sql_clauses << "age > ?"
    sql_args << params[:age_greater_than]
  end
  .....
  @results = Model.where(sql_clauses.join(" and "), sql_args.join(", "))

end

これで、sql_clauses配列がwhereメソッドに問題なく送信されます。ただし、2番目の引数は、単一の文字列を返し、各「?」に対応する個々の変数を期待しているため、爆破されます。sql_clauses配列に表示されるフィールド。私は、KandadaBogguが提供する、レール内の条件のComine配列に関するソリューションを試しました。これらのオプションはどちらも機能しませんでしたが、1つではなく2つのアレイを使用していることが原因である可能性があります。

誰かが私の問題の解決策を知っていますか?

4

2 に答える 2

5

Rails 3で動的クエリを作成するために文字列を使用する必要はありません。select、where、order、limitなどのActiveRecordメソッドは、複数のデータベース呼び出しをトリガーせずにチェーンできるActiveRecord::Relationオブジェクトを返します。

cars = Car.where(:colour => 'black') # No database queries are generated here.
rich_ppls_cars = cars.order('cars.price DESC').limit(10) # Still no db queries.

、、、、またはActiveRecord :: Relationshipオブジェクトを呼び出す.allと、.firstdbが照会されます。.last.each

サンプルコード

次の列を使用してモデルをクエリしていると仮定します。

  • 名前
  • 経過時間

そして、次のようなparamsハッシュがあります。

{ :elapsed_time => 34, :age_greater_than => 14, :max_rows => 20 }

コントローラのアクションは次のようになります。

def results
    query = ModelName.select([:name, :elapsed_time, :age])
    query = query.where(:elapsed_time => params[:elapsed_time])  if params[:elapsed_time].present?
    query = query.where('age > ?', params[:age_greater_than])  if params[:age_greater_then].present?
    query = query.limit(params[:max_rows])  if params[:max_rows].present?
    @dynamic_query = query
end

を使用してparamsキーの存在をテストしていることに注意してください.present?。これにより、paramsハッシュ内の空白の文字列を有効なデータとして誤って解釈することを防ぎます。

参考資料

于 2012-05-27T19:08:52.383 に答える
1

次のようなものを試してください。

def results
  sql_clauses = []
  sql_clauses << "elapsed_time = :elapsed_time" if params[:elapsed_time]
  sql_clauses << "age > :age_greater_than" if params[:age_greater_than]
  .....
  @results = Model.where(sql_clauses.join(" and "), params)
end

ここで、構築条件のさまざまな異なる構文をサポートします。

含めることができるファイルがたくさんある場合は、次のようにマッピング辞書を作成します。

map = {
   :elapsed_time => "elapsed_time =",
   :age_greater_than => "age >"
}

次に、paramsキーをループして、に存在する場合は句を作成しmapます。

于 2012-05-24T20:57:04.433 に答える