ハッシュに基づいてSQLクエリを作成できます。最も一般的なアプローチは生のSQLであり、ActiveRecord
で実行できます。 。
正しいアイデアを提供するためのコンセプトコードは次のとおりです。
query_select = "select * from "
query_where = ""
tables = [] # for selecting from all tables
hash.each do |table, values|
table_name = table.constantize.table_name
tables << table_name
values.each do |q|
query_where += " AND " unless query_string.empty?
query_where += "'#{ActiveRecord::Base.connection.quote(table_name)}'."
query_where += "'#{ActiveRecord::Base.connection.quote(q[fieldName)}'"
if q[:operator] == "starts with" # this should be done with an appropriate method
query_where += " LIKE '#{ActiveRecord::Base.connection.quote(q[val)}%'"
end
end
end
query_tables = tables.join(", ")
raw_query = query_select + query_tables + " where " + query_where
result = ActiveRecord::Base.connection.execute(raw_query)
result.to_h # not required, but raw results are probably easier to handle as a hash
これは何をしますか:
-
query_select
結果に必要な情報を指定します -
query_where
すべての検索条件を作成し、入力をエスケープしてSQLインジェクションを防止します -
query_tables
検索する必要があるすべてのテーブルのリストです -
table_name = table.constantize.table_name
モデルで使用されるSQLtable_nameが表示されます -
raw_query
上記の部分からの実際の結合SQLクエリです -
ActiveRecord::Base.connection.execute(raw_query)
データベースでSQLを実行します
SQLインジェクションを防ぐために、ユーザーが送信した入力はすべて引用符で囲み、適切にエスケープしてください。
この例では、作成されたクエリは次のようになります。
select * from companies, categories where 'companies'.'name' LIKE 'a%' AND 'companies'.'hq_city' = 'karachi' AND 'categories'.'name' NOT LIKE '%ECommerce%'
このアプローチでは、関連するテーブルを結合するための追加のロジックが必要になる場合があります。あなたの場合、company
およびcategory
関連付けがある場合は、このようなものをquery_where
に追加する必要があります
"AND 'company'.'category_id' = 'categories'.'id'"
簡単なアプローチ: クエリ可能なモデル/テーブルのすべてのペアに対してハッシュを作成し、そこに適切な結合条件を格納できます。このハッシュは、中規模のプロジェクトでも複雑すぎないようにする必要があります。
ハードアプローチ: has_many
がある場合、これは自動的に実行できます 、has_one
およびbelongs_to
モデルで適切に定義されています。モデルの関連付けは、reflect_on_all_associations<を使用して取得できます。 / a> 。 Breath-First-Search
を実装する またはDepth-First Search
アルゴリズムを実行し、任意のモデルから開始して、json入力から他のモデルとの一致する関連付けを検索します。 json入力から未訪問のモデルがなくなるまで、新しいBFS/DFSの実行を開始します。見つかった情報から、すべての結合条件を導き出し、それらをwhere
の式として追加できます。 上で説明した生のSQLアプローチの節。さらに複雑ですが、データベースのschema
を読み取ることも実行可能です。 foreign keys
を探すことにより、ここで定義されているのと同様のアプローチを使用します 。
関連付けの使用: それらすべてがhas_many
に関連付けられている場合 / has_one
、ActiveRecord
で結合を処理できます joins
を使用する inject
を使用したメソッド このような「最も重要な」モデルについて:
base_model = "Company".constantize
assocations = [:categories] # and so on
result = assocations.inject(base_model) { |model, assoc| model.joins(assoc) }.where(query_where)
これは何をしますか:
- base_modelを開始入力として
に渡します。 Enumerable.inject 、input.send(:joins、:assoc)を繰り返し呼び出します(私の例では、これは Company.send(:joins, :categories)
を実行します これは`Company.categories
と同等です - 結合された結合では、where条件(上記のように構築された)を実行します
免責事項 必要な正確な構文は、使用するSQL実装によって異なる場合があります。