gpt4 book ai didi

ruby-on-rails - 使用 OR 组合多个范围或 where 查询

转载 作者:行者123 更新时间:2023-12-04 05:38:12 25 4
gpt4 key购买 nike

我如何以这样的方式获取 arel 组件,以便我可以执行以下操作:

queries = []
queries << MyModel.some_scope.get_the_arel_component
queries << MyModel.some_scope_with_param("Dave").get_the_arel_component
queries << MyModel.where(:something => 'blah').get_the_arel_component
queries << MyModel.some_scope_with_join_and_merge.get_arel_component
# etc ... (may be any number of queries)

# join each query with OR
combined_query = nil
queries.each do |query|
combined_query ||= query
combined_query = combined_query.or(q)
end

# run the query so it just works
MyModel.where(combined_query)

我遇到了一些类似问题的公认答案的问题。

假设我有一个这样的类(class):
class Patient
has_one :account

scope :older_than, ->(date) { where(arel_table[:dob].lt(date)) }
scope :with_gender, ->(gender) { where(:gender => gender) }
scope :with_name_like, ->(name) { where("lower(name) LIKE ?", name.downcase) }
scope :in_arrears, -> { joins(:account).merge( Account.in_arrears ) }
end

目标是将任何范围或 where 子句与 OR 结合起来。

One way将是 Patient.with_name_like("Susan") | Patient.with_name_like("Dave") .这似乎单独运行每个单独的查询,而不是组合成单个查询。我已经排除了这个解决方案。

Another method仅在某些情况下有效的是:
# this fails because `where_values` for the `with_name_like` scope returns a string
sues = Patient.with_name_like("Susan").where_values.reduce(:and)
daves = Patient.with_name_like("Dave").where_values.reduce(:and)
Patient.where(sues.or(daves))

# this works as `where_values` returns an `Arel::Nodes::Equality` object
ages = Patient.older_than(7.years.ago).where_values.reduce(:and)
males = Patients.with_gender('M').where_values.reduce(:and)
Patient.where(ages.or(males))

# this fails as `in_arrears` scope requires a joins
of_age = Patient.older_than(18.years.ago).where_values.reduce(:and)
arrears = Patients.in_arrears.where_values.reduce(:and)
Patient.where(of_age.or(arrears)) # doesn't work as no join on accounts
Patient.join(:account).where(of_age.or(arrears)) # does work as we have our join

综上所述,ORing 查询的问题出现在 where 时。传递一个字符串或查询需要连接。

我很确定 where将传递给它的任何东西转换为一个 arel 对象,这只是获取正确的部分并以正确的方式重新组合它们的问题。我只是还没有设法解决它。

最好的答案是只使用 ActiveRecord 和 AREL 而不是第三方库。

最佳答案

既然您愿意使用第三方库,那么 Ransack 怎么样? ?

它有一个非常健壮的实现,允许各种 and 和 or 条件组合,并且也适用于相关模型。

对于像您这样有一些预定义查询/范围的用例,我希望用户能够从中选择并运行 or结合它们,我使用 ransack 的开箱即用实现,然后在 View 级别,我使用 javascript 插入带有值的隐藏字段,这些值将导致 Controller 中预期的结构化参数哈希ransack。

您可以使用 ransack helpers 在 View 中轻松定义所有范围。您的代码应如下所示:

Controller

def index
@q = Patient.search(params[:q])
@patients = @q.result(distinct: true)
end

查看
<%= search_form_for @q do |f| %>
<%= f.label :older_than %>
<%= f.date_field :dob_lt %>
<%= f.label :with_gender %>
<%= f.text_field :gender_eq %>
<%= f.label :with_name_like %>
<%= f.text_field :name_cont %>
<%= f.label :in_arrears_exceeding %>
<%= f.text_field :accounts_total_due_gte %>
<%= f.submit %>
<% end %>

另外,如果您想更好地控制 andingoring看看 complex search form builder使用 ransack 的例子。

关于ruby-on-rails - 使用 OR 组合多个范围或 where 查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23097638/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com