検索結果をフィルタリングする動的なクエリメソッドを構築しようとしています。Rails-検索結果をフィルタリングする動的クエリを構築する
私のモデルは:
class Order < ActiveRecord::Base
scope :by_state, -> (state) { joins(:states).where("states.id = ?", state) }
scope :by_counsel, -> (counsel) { where("counsel_id = ?", counsel) }
scope :by_sales_rep, -> (sales) { where("sales_id = ?", sales) }
scope :by_year, -> (year) { where("title_number LIKE ?", "%NYN#{year}%") }
has_many :properties, :dependent => :destroy
has_many :documents, :dependent => :destroy
has_many :participants, :dependent => :destroy
has_many :states, through: :properties
belongs_to :action
belongs_to :role
belongs_to :type
belongs_to :sales, :class_name => 'Member'
belongs_to :counsel, :class_name => 'Member'
belongs_to :deal_name
end
class Property < ActiveRecord::Base
belongs_to :order
belongs_to :state
end
class State < ActiveRecord::Base
has_many :properties
has_many :orders, through: :properties
end
私は、デフォルトですべての注文を表示するページがあります。私は結果のフィルタリングを可能にするチェックボックスを持っています。フィルターには、年、州、セールス、カウンセルがあります。クエリの例は次のとおりです。sales_id unlimited idsを持つ状態(has_many〜)NJ、PA、CAなどの2016年、2015年のすべての注文(「order.title_number LIKE?」、「%NYN#{year}%」) counsel_id無制限のcounsel_id。
ナッツシェルでは、ユーザーがチェックするすべてのオプションを考慮した1つのクエリを作成する方法を理解しようとしています。ここに私の現在のクエリのコードは次のとおりです。
def Order.query(opt = {})
results = []
orders = []
if !opt["state"].empty?
opt["state"].each do |value|
if orders.empty?
orders = Order.send("by_state", value)
else
orders << Order.send("by_state", value)
end
end
orders = orders.flatten
end
if !opt["year"].empty?
new_orders = []
opt["year"].each do |y|
new_orders = orders.by_year(y)
results << new_orders
end
end
if !opt["sales_id"].empty?
end
if !opt["counsel_id"].empty?
end
if !results.empty?
results.flatten
else
orders.flatten
end
end
ここで私は、フィルタリングの無制限の量を可能にするために出ているソリューションです。
def self.query(opts = {})
orders = Order.all
opts.delete_if { |key, value| value.blank? }
const_query = ""
state_query = nil
counsel_query = nil
sales_query = nil
year_query = nil
queries = []
if opts["by_year"]
year_query = opts["by_year"].map do |val|
" title_number LIKE '%NYN#{val}%' "
end.join(" or ")
queries << year_query
end
if opts["by_sales_rep"]
sales_query = opts["by_sales_rep"].map do |val|
" sales_id = '#{val}' "
end.join(" or ")
queries << sales_query
end
if opts["by_counsel"]
counsel_query = opts["by_counsel"].map do |val|
" counsel_id = '#{val}' "
end.join(" or ")
queries << counsel_query
end
if opts["by_state"]
state_query = opts["by_state"].map do |val|
"states.id = '#{val}'"
end.join(" or ")
end
query_string = queries.join(" AND ")
if state_query
@orders = Order.joins(:states).where("#{state_query}")
@orders = @orders.where(query_string)
else
@orders = orders.where("#{query_string}")
end
@orders.order("title_number DESC")
end
これらすべてのクエリを呼び出すメソッドが1つ必要であることを意味していますか?あなたのコードではあなたがby_stateを呼び出すので、私は年が別のものであると仮定します。 1つのクエリではありません。その場合(4つのクエリの場合)、私は実際に何が問題なのかわかりません。 –
はい1つのクエリですべてを呼び出すとします。現在、私はクエリメソッドに渡された引数に基づいて個別にクエリを呼び出そうとしています。引数の例は{"year" => ["16"、 "15"]、 "state" => ["31"、 "39"]}です。私の問題は、_by_yearを_by_state条件で複数回呼び出すことができると思います。しかし、私は何年になるか、国家が送られるかはわかりません。 @Joel_Blum –
'scope 'にしたがってopt_keysの名前を付けてみてみてはいかがでしょうか。 '{by_state:[" 31 "、" 39 "]、by_year:" 16 "}'あなたは一般的に 'opts.inject(Order){| order、(scope、value)| order.public_send(スコープ、値)} '。これにより、指定されたすべてのフィルタを持つActiveRecord :: Relationが構築されます。それであなたがそれに取り組むと、その質問は実際に発動します。 BTW複数の年を渡す場合は、 'by_year'スコープを修正する必要があります。 – engineersmnky