我正在嘗試構建一個動態查詢方法來過濾搜索結果。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
我有一個頁面,我默認顯示的所有訂單。我想要複選框以允許篩選結果。過濾器是:年,州,銷售和法律顧問。一個查詢的例子是:在2016年,2015年的所有訂單(「order.title_number LIKE?」,「%NYN#{year}%」)在狀態(has_many到NJ),PA,CA等中有sales_id unlimited IDS和counsel_id無限counsel_ids。
在堅果殼中,我試圖找出如何創建一個查詢,考慮到用戶檢查的所有選項。這裏是我目前的查詢代碼:
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
你的意思是你需要一個方法來調用所有這些查詢嗎?因爲在你的代碼中你調用了by_state,這是一個,那麼我認爲year是另一個等,等等。所以這不是一個查詢。在這種情況下(如果它是4個查詢)我真的不知道有什麼問題... –
是的我想用一個查詢調用所有東西。目前我試圖根據傳遞給查詢方法的參數分別調用查詢。參數的例子是{「year」=> [「16」,「15」],「state」=> [「31」,「39」]}。我認爲我的問題是能夠使用_by_state條件多次調用_by_year。但是我不知道多少年,國家會發送。我希望這是有道理的@Joel_Blum –
爲什麼不嘗試按照'scopes'命名opt_keys '{by_state:[「31」,「39」],by_year:「16」}''那麼你可以一般地使用'opts.inject(Order){| order,(scope,value) order.public_send(範圍,值)}'。這將與指定的所有過濾器建立一個ActiveRecord :: Relation。然後,當你採取行動時,查詢實際上會觸發。順便說一句如果你想要傳遞多年,你將需要修復'by_year'範圍。 – engineersmnky