Resolving application_controller.rb merge conflicts, tests pass.
[arvados.git] / services / api / lib / record_filters.rb
1 # Expects:
2 #   @where
3 #   @filters
4 #   +model_class+
5 # Operates on:
6 #   @objects
7 module RecordFilters
8
9   def record_filters filters, ar_table_name
10     cond_out = []
11     param_out = []
12
13     filters.each do |filter|
14       attr, operator, operand = filter
15       if !filter.is_a? Array
16         raise ArgumentError.new("Invalid element in filters array: #{filter.inspect} is not an array")
17       elsif !operator.is_a? String
18         raise ArgumentError.new("Invalid operator '#{operator}' (#{operator.class}) in filter")
19       elsif !model_class.searchable_columns(operator).index attr.to_s
20         raise ArgumentError.new("Invalid attribute '#{attr}' in filter")
21       end
22       case operator.downcase
23       when '=', '<', '<=', '>', '>=', 'like'
24         if operand.is_a? String
25           cond_out << "#{ar_table_name}.#{attr} #{operator} ?"
26           if (# any operator that operates on value rather than
27               # representation:
28               operator.match(/[<=>]/) and
29               model_class.attribute_column(attr).type == :datetime)
30             operand = Time.parse operand
31           end
32           param_out << operand
33         elsif operand.nil? and operator == '='
34           cond_out << "#{ar_table_name}.#{attr} is null"
35         else
36           raise ArgumentError.new("Invalid operand type '#{operand.class}' "\
37                                   "for '#{operator}' operator in filters")
38         end
39       when 'in'
40         if operand.is_a? Array
41           cond_out << "#{ar_table_name}.#{attr} IN (?)"
42           param_out << operand
43         else
44           raise ArgumentError.new("Invalid operand type '#{operand.class}' "\
45                                   "for '#{operator}' operator in filters")
46         end
47       when 'is_a'
48         operand = [operand] unless operand.is_a? Array
49         cond = []
50         operand.each do |op|
51           cl = ArvadosModel::kind_class op
52           if cl
53             cond << "#{ar_table_name}.#{attr} like ?"
54             param_out << cl.uuid_like_pattern
55           else
56             cond << "1=0"
57           end
58         end
59         cond_out << cond.join(' OR ')
60       end
61     end
62
63     {:cond_out => cond_out, :param_out => param_out}
64   end
65
66 end