提问人:willyab 提问时间:10/5/2023 最后编辑:mechnicovwillyab 更新时间:10/5/2023 访问量:35
如何在 rails 中构建动态范围
How to build a dynamic scope in rails
问:
在给定要排除的可变长度元素数组的情况下,如何构造动态范围搜索,如下所示:
class Participant < ApplicationRecord
scope exclude_names, -> (['%name1%', '%name2%', '%name3%', ...]) {
where.not(Participant.arel_table[:name_search].matches('%name1%').or(
Participant.arel_table[:name_search].matches('%name2%').or(
Participant.arel_table[:name_search].matches('%name3%').or(
...
}
但动态完成,因为name_list是可变长度的。
答:
0赞
Siim Liiser
10/5/2023
#1
在一个循环中创建所有条件,然后将它们与 -s 组合到您的条件中。or
scope :exclude_names, -> (names) do
clauses = names.map do |name|
Participant.arel_table[:name_search].matches(name)
end
condition = clauses.inject(:or)
where.not(condition)
end
0赞
mechnicov
10/5/2023
#2
我建议使用方法并累积条件,遍历排除的名称。您也不需要在作用域内显式调用类名,因为它是类方法does_not_match
AND
class Participant < ApplicationRecord
scope :exclude_names, ->(*names_to_exclude) {
query = names_to_exclude.reduce(nil) do |q, name|
condition = arel_table[:name_search].does_not_match("%#{name}%")
q&.and(condition) || condition
end
where(query)
}
end
之后,您可以调用此作用域
Participant.exclude_names('name1')
# SELECT * FROM participants
# WHERE name_search NOT LIKE '%name1%'
Participant.exclude_names('name1', 'name2')
# SELECT * FROM participants
# WHERE name_search NOT LIKE '%name1%'
# AND name_search NOT LIKE '%name2%'
Participant.exclude_names(%w[name1 name2])
# SELECT * FROM participants
# WHERE name_search NOT LIKE '%name1%'
# AND name_search NOT LIKE '%name2%'
当然,您可以在您的问题中使用 like,在这种情况下,它将是这样的OR
class Participant < ApplicationRecord
scope :exclude_names, ->(*names_to_exclude) {
query = names_to_exclude.reduce(nil) do |q, name|
condition = arel_table[:name_search].matches("%#{name}%")
q&.or(condition) || condition
end
where.not(query)
}
end
之后,您可以调用此范围,与以前的查询进行比较
Participant.exclude_names('name1')
# SELECT * FROM participants
# WHERE NOT (name_search LIKE '%name1%')
Participant.exclude_names('name1', 'name2')
# SELECT * FROM participants
# WHERE NOT (name_search LIKE '%name1%' OR name_search LIKE '%name2%')
Participant.exclude_names(%w[name1 name2])
# SELECT * FROM participants
# WHERE NOT (name_search LIKE '%name1%' OR name_search LIKE '%name2%')
评论