我在Rails 5上。
我必须处理一个非常复杂的查询,其中包含多个相同的where子句:
::AllocatedBudget.joins(:account_code, :budget, account_code: [:place],
budget: [:fiscal_year, :budget_state])
.where(immeuble: { id: place.id })
.where(situation_budget: { codesituation: ['A', 'V']})
.where(plan_comptable: { supprime: 'false' })
.where(budget: { supprime: 'false'})
.where(situation_budget: { supprime: 'false' })
.where(budget_previsionnel: { supprime: 'false' })
.where(exercice_comptable: { supprime: 'false' })
首先,您必须知道我的模型已连接到具有丑陋名称的旧数据库。我注意到ActiveRecord需要自定义名称而不是模型的名称来执行查询。我不知道为什么,但它只是那样工作......如果有人能解释它会很好;)
我真正的问题是:我能以更好的方式写出来吗?有很多时间相同的where子句“supprime ='false'”。
非常感谢! :)
答案 0 :(得分:1)
我会将问题分解为两个步骤
where
。 所以第一步是这样的。
same_conditions_list = [
:plan_comptable,
:budget,
:situation_budget,
:budget_previsionnel,
:exercice_comptable
]
same_conditions_key_values = same_conditions_list.inject({}) do |conditions, condition|
conditions[condition] = { supprime: 'false' }
conditions
end
same_conditions = Hash[same_conditions_key_values]
all_conditions = same_conditions.merge({
immeuble: { id: "place.id" }
})
之后all_conditions
将等于此
{
:plan_comptable=>{:supprime=>"false"},
:budget=>{:supprime=>"false"},
:situation_budget=>{:supprime=>"false"},
:budget_previsionnel=>{:supprime=>"false"},
:exercice_comptable=>{:supprime=>"false"},
:immeuble=>{:id=>"place.id"}
}
然后第二步就是
::AllocatedBudget.joins(:account_code, :budget, account_code: [:place],
budget: [:fiscal_year, :budget_state])
.where(all_conditions)
答案 1 :(得分:0)
最后我尝试了设计模式"查询对象"混合使用AndrewSwerlick的解决方案
module QueryObject
class AllocatedBudgetQuery
def self.call(filters = {}, relation = ::AllocatedBudget.all)
new(filters, relation).tap(&:call)
end
# filter can have the key/value as follow (key are symbols) :
# place_id/string
# current_fiscal_year/boolean
# budget_state/['A', 'V', '*']
def initialize(filters = {}, relation = ::AllocatedBudget.all)
@relation = relation
@filters = filters
end
def call
conditions = {
budget_previsionnel: { supprime: 'false' },
budget: { supprime: 'false' }
}
# place filter
conditions = conditions.merge(immeuble: { id: @filters[:place_id] }) if @filters.key?(:place_id)
# situation budget filter
conditions = conditions.merge(situation_budget: { codesituation: @filters[:budget_state] }) if @filters.key?(:budget_state)
# main extract
@relation = @relation.joins(:account_code,
account_code: [:place],
budget: %i[fiscal_year budget_state])
.where(conditions)
# current fiscal year filter
@relation = @relation.where("#{Date.today.to_s} between exercice_comptable.datedebutexercice and exercice_comptable.datefinexercice") if @filters.key?(:current_fiscal_year)
end
end
end