protected
- def load_where_param
- if params[:where].nil? or params[:where] == ""
- @where = {}
- elsif params[:where].is_a? Hash
- @where = params[:where]
- elsif params[:where].is_a? String
- begin
- @where = Oj.load(params[:where])
- raise unless @where.is_a? Hash
- rescue
- raise ArgumentError.new("Could not parse \"where\" param as an object")
- end
- end
- @where = @where.with_indifferent_access
- end
-
- def load_filters_param
- @filters ||= []
- if params[:filters].is_a? Array
- @filters += params[:filters]
- elsif params[:filters].is_a? String and !params[:filters].empty?
- begin
- f = Oj.load params[:filters]
- raise unless f.is_a? Array
- @filters += f
- rescue
- raise ArgumentError.new("Could not parse \"filters\" param as an array")
- end
- end
- end
-
- def load_limit_offset_order_params
- if params[:limit]
- unless params[:limit].to_s.match(/^\d+$/)
- raise ArgumentError.new("Invalid value for limit parameter")
- end
- @limit = params[:limit].to_i
- else
- @limit = DEFAULT_LIMIT
- end
-
- if params[:offset]
- unless params[:offset].to_s.match(/^\d+$/)
- raise ArgumentError.new("Invalid value for offset parameter")
- end
- @offset = params[:offset].to_i
- else
- @offset = 0
- end
-
- @orders = []
- if params[:order]
- params[:order].split(',').each do |order|
- attr, direction = order.strip.split " "
- direction ||= 'asc'
- if attr.match /^[a-z][_a-z0-9]+$/ and
- model_class.columns.collect(&:name).index(attr) and
- ['asc','desc'].index direction.downcase
- @orders << "#{table_name}.#{attr} #{direction.downcase}"
- end
- end
- end
- if @orders.empty?
- @orders << "#{table_name}.modified_at desc"
- end
- end
-
+ def find_objects_for_index
+ @objects ||= model_class.readable_by(current_user)
+ apply_where_limit_order_params
+ end
+
def apply_where_limit_order_params
- ar_table_name = @objects.table_name
- if @filters.is_a? Array and @filters.any?
- cond_out = []
- param_out = []
- @filters.each do |filter|
- attr, operator, operand = filter
- if !filter.is_a? Array
- raise ArgumentError.new("Invalid element in filters array: #{filter.inspect} is not an array")
- elsif !operator.is_a? String
- raise ArgumentError.new("Invalid operator '#{operator}' (#{operator.class}) in filter")
- elsif !model_class.searchable_columns(operator).index attr.to_s
- raise ArgumentError.new("Invalid attribute '#{attr}' in filter")
- end
- case operator.downcase
- when '=', '<', '<=', '>', '>=', 'like'
- if operand.is_a? String
- cond_out << "#{ar_table_name}.#{attr} #{operator} ?"
- if (# any operator that operates on value rather than
- # representation:
- operator.match(/[<=>]/) and
- model_class.attribute_column(attr).type == :datetime)
- operand = Time.parse operand
- end
- param_out << operand
- elsif operand.nil? and operator == '='
- cond_out << "#{ar_table_name}.#{attr} is null"
- else
- raise ArgumentError.new("Invalid operand type '#{operand.class}' "\
- "for '#{operator}' operator in filters")
- end
- when 'in'
- if operand.is_a? Array
- cond_out << "#{ar_table_name}.#{attr} IN (?)"
- param_out << operand
- else
- raise ArgumentError.new("Invalid operand type '#{operand.class}' "\
- "for '#{operator}' operator in filters")
- end
- when 'is_a'
- operand = [operand] unless operand.is_a? Array
- cond = []
- operand.each do |op|
- cl = ArvadosModel::kind_class op
- if cl
- cond << "#{ar_table_name}.#{attr} like ?"
- param_out << cl.uuid_like_pattern
- else
- cond << "1=0"
- end
- end
- cond_out << cond.join(' OR ')
- end
- end
- if cond_out.any?
- @objects = @objects.where(cond_out.join(' AND '), *param_out)
- end
+ ft = record_filters @filters
+ if ft[:cond_out].any?
+ @objects = @objects.where(ft[:cond_out].join(' AND '), *ft[:param_out])
end
+
if @where.is_a? Hash and @where.any?
conditions = ['1=1']
@where.each do |attr,value|