我正在构建一个 Rails 5.2 应用程序。 在这个应用程序中,我有一个 QueryBuilder 类,我的用户可以使用它来构建数据查询。 该类使用 JSON 对象来构建和运行查询。
我正在使用这里的代码:
https://stackoverflow.com/a/47120339/339067
数据
data = [{
className: 'Project',
relation: 'Project',
field: 'title',
operator: 'starts_with',
chainer: 'AND',
val: 'Rebranding'
}, {
className: 'Project',
relation: 'Project',
field: 'id',
operator: 'not_equals',
chainer: 'AND NOT',
val: '10'
}]
查询构建器
class QueryBuilder
def initialize(data)
@data = prepare_data(data)
end
def find_records
queries = @data.group_by {|e| e[:model]}
queries.map do |k, v|
puts k
puts v
q = v.map do |f|
{
field: "#{f[:table_name]}.#{f[:field]} #{read_operator(f[:operator])} ?",
value: value_based_on_operator(f[:val], f[:operator])
}
end
db_query = q.map {|e| e[:field]}.join(" AND ")
values = q.map {|e| e[:value]}
{"#{k}": k.constantize.joins(join_hash(v)).where(db_query, *values)}
end
end
private
def join_hash(array_of_relations)
hash = {}
array_of_relations.each do |f|
hash.merge!(array_to_hash(f[:joins]))
end
hash.map do |k, v|
if v.nil?
k
else
{"#{k}": v}
end
end
end
def read_operator(operator)
case operator
when 'equals'
'='
when 'not_equals'
'!='
when 'larger_than'
'>'
when 'smaller_than'
'<'
when 'starts_with'
'LIKE'
end
end
def value_based_on_operator(value, operator)
case operator
when 'equals'
value
when 'not_equals'
value
when 'larger_than'
value
when 'smaller_than'
value
when 'starts_with'
"%#{value}"
end
end
def prepare_data(data)
data.each do |record|
record.tap do |f|
f[:model] = f[:relation].split('.')[0]
f[:joins] = f[:relation].split('.').drop(1)
f[:table_name] = f[:className].constantize.table_name
end
end
end
def array_to_hash(array)
if array.length < 1
{}
elsif array.length == 1
{"#{array[0]}": nil}
elsif array.length == 2
{"#{array[0]}": array[1]}
else
{"#{array[0]}": array_to_hash(array.drop(1))}
end
end
end
我是这样用的
query = QueryBuilder.new(data)
render plain: query.find_records.to_json, status: 200
如何使用“chainer”对象值而不是对上述类中的 AND 进行硬编码?