[ARVADOS] updated: 04cc77648cc62c73433801475c27ede4ceb76c8b
git at public.curoverse.com
git at public.curoverse.com
Tue Apr 22 17:12:15 EDT 2014
Summary of changes:
.../api/app/controllers/application_controller.rb | 171 +-------------------
services/api/lib/eventbus.rb | 50 ++++++-
services/api/lib/load_param.rb | 39 +++++
services/api/lib/record_filters.rb | 145 +++++++++++++++++
4 files changed, 235 insertions(+), 170 deletions(-)
create mode 100644 services/api/lib/load_param.rb
create mode 100644 services/api/lib/record_filters.rb
via 04cc77648cc62c73433801475c27ede4ceb76c8b (commit)
from fa257c28461627fe6700dd8fd2152e380f8725d4 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit 04cc77648cc62c73433801475c27ede4ceb76c8b
Author: Peter Amstutz <peter.amstutz at curoverse.com>
Date: Tue Apr 22 17:12:12 2014 -0400
Refactored load_filters_param and apply_where_limit_order_params into lib/
directory so that EventBus can use them. Started adding filtering to EventBus, this is incomplete.
diff --git a/services/api/app/controllers/application_controller.rb b/services/api/app/controllers/application_controller.rb
index 033eccd..9c5497b 100644
--- a/services/api/app/controllers/application_controller.rb
+++ b/services/api/app/controllers/application_controller.rb
@@ -1,6 +1,11 @@
+require 'load_param'
+require 'record_filters'
+
class ApplicationController < ActionController::Base
include CurrentApiClient
include ThemesForRails::ActionController
+ include LoadParam
+ include RecordFilters
respond_to :json
protect_from_forgery
@@ -103,178 +108,12 @@ class ApplicationController < ActionController::Base
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 find_objects_for_index
@objects ||= model_class.readable_by(current_user)
apply_where_limit_order_params
end
- def apply_where_limit_order_params
- if @filters.is_a? Array and @filters.any?
- cond_out = []
- param_out = []
- @filters.each do |attr, operator, operand|
- if !model_class.searchable_columns(operator).index attr.to_s
- raise ArgumentError.new("Invalid attribute '#{attr}' in condition")
- end
- case operator.downcase
- when '=', '<', '<=', '>', '>=', 'like'
- if operand.is_a? String
- cond_out << "#{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
- end
- when 'in'
- if operand.is_a? Array
- cond_out << "#{table_name}.#{attr} IN (?)"
- param_out << operand
- end
- when 'is_a'
- operand = [operand] unless operand.is_a? Array
- cond = []
- operand.each do |op|
- cl = ArvadosModel::kind_class op
- if cl
- cond << "#{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
- end
- if @where.is_a? Hash and @where.any?
- conditions = ['1=1']
- @where.each do |attr,value|
- if attr.to_s == 'any'
- if value.is_a?(Array) and
- value.length == 2 and
- value[0] == 'contains' then
- ilikes = []
- model_class.searchable_columns('ilike').each do |column|
- ilikes << "#{table_name}.#{column} ilike ?"
- conditions << "%#{value[1]}%"
- end
- if ilikes.any?
- conditions[0] << ' and (' + ilikes.join(' or ') + ')'
- end
- end
- elsif attr.to_s.match(/^[a-z][_a-z0-9]+$/) and
- model_class.columns.collect(&:name).index(attr.to_s)
- if value.nil?
- conditions[0] << " and #{table_name}.#{attr} is ?"
- conditions << nil
- elsif value.is_a? Array
- if value[0] == 'contains' and value.length == 2
- conditions[0] << " and #{table_name}.#{attr} like ?"
- conditions << "%#{value[1]}%"
- else
- conditions[0] << " and #{table_name}.#{attr} in (?)"
- conditions << value
- end
- elsif value.is_a? String or value.is_a? Fixnum or value == true or value == false
- conditions[0] << " and #{table_name}.#{attr}=?"
- conditions << value
- elsif value.is_a? Hash
- # Not quite the same thing as "equal?" but better than nothing?
- value.each do |k,v|
- if v.is_a? String
- conditions[0] << " and #{table_name}.#{attr} ilike ?"
- conditions << "%#{k}%#{v}%"
- end
- end
- end
- end
- end
- if conditions.length > 1
- conditions[0].sub!(/^1=1 and /, '')
- @objects = @objects.
- where(*conditions)
- end
- end
-
- if params[:limit]
- begin
- @limit = params[:limit].to_i
- rescue
- raise ArgumentError.new("Invalid value for limit parameter")
- end
- else
- @limit = 100
- end
- @objects = @objects.limit(@limit)
-
- orders = []
-
- if params[:offset]
- begin
- @objects = @objects.offset(params[:offset].to_i)
- @offset = params[:offset].to_i
- rescue
- raise ArgumentError.new("Invalid value for limit parameter")
- end
- 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
- @objects = @objects.order(orders.join ", ")
- end
-
def resource_attrs
return @attrs if @attrs
@attrs = params[resource_name]
diff --git a/services/api/lib/eventbus.rb b/services/api/lib/eventbus.rb
index 26674b7..646ee83 100644
--- a/services/api/lib/eventbus.rb
+++ b/services/api/lib/eventbus.rb
@@ -1,14 +1,52 @@
require 'eventmachine'
require 'oj'
require 'faye/websocket'
+require 'record_filters'
module Faye
class WebSocket
attr_accessor :user
attr_accessor :last_log_id
+ attr_accessor :filters
end
end
+class Filter
+ include LoadParam
+
+ def initialize p
+ @p = p
+ load_filters_param
+ end
+
+ def params
+ @p
+ end
+
+ def filters
+ @filters
+ end
+end
+
+class FilterController
+ include RecordFilters
+
+ def initialize(f, o)
+ @filters = f
+ @objects = o
+ apply_where_limit_order_params
+ end
+
+ def each &b
+ @objects.each &b
+ end
+
+ def params
+ {}
+ end
+
+end
+
class EventBus
include CurrentApiClient
@@ -26,20 +64,24 @@ class EventBus
end
ws.user = current_user
+ ws.filters = []
sub = @channel.subscribe do |msg|
Log.where(id: msg.to_i).each do |l|
+ ws.last_log_id = msg.to_i
if rsc = ArvadosModel::resource_class_for_uuid(l.object_uuid)
- rsc.readable_by(ws.user).where(uuid: l.object_uuid).each do
- ws.send(l.as_api_response.to_json)
+ permitted = rsc.readable_by(ws.user).where(uuid: l.object_uuid)
+ ws.filters.each do |filter|
+ FilterController.new(filter, permitted).each do
+ ws.send(l.as_api_response.to_json)
+ end
end
end
- ws.last_log_id = msg.to_i
end
end
ws.on :message do |event|
- #puts "got #{event.data}"
+ ws.filters = Filter.new oj.parse(event.data)
end
ws.on :close do |event|
diff --git a/services/api/lib/load_param.rb b/services/api/lib/load_param.rb
new file mode 100644
index 0000000..f1c3198
--- /dev/null
+++ b/services/api/lib/load_param.rb
@@ -0,0 +1,39 @@
+# Expects:
+# +params+ Hash
+# Sets:
+# @where, @filters
+
+module LoadParam
+
+ 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
+
+end
diff --git a/services/api/lib/record_filters.rb b/services/api/lib/record_filters.rb
new file mode 100644
index 0000000..fab16bb
--- /dev/null
+++ b/services/api/lib/record_filters.rb
@@ -0,0 +1,145 @@
+# Expects:
+# @where
+# @filters
+# +model_class+
+# Operates on:
+# @objects
+module RecordFilters
+
+ def apply_where_limit_order_params
+ if @filters.is_a? Array and @filters.any?
+ cond_out = []
+ param_out = []
+ @filters.each do |attr, operator, operand|
+ if !model_class.searchable_columns(operator).index attr.to_s
+ raise ArgumentError.new("Invalid attribute '#{attr}' in condition")
+ end
+ case operator.downcase
+ when '=', '<', '<=', '>', '>=', 'like'
+ if operand.is_a? String
+ cond_out << "#{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
+ end
+ when 'in'
+ if operand.is_a? Array
+ cond_out << "#{table_name}.#{attr} IN (?)"
+ param_out << operand
+ end
+ when 'is_a'
+ operand = [operand] unless operand.is_a? Array
+ cond = []
+ operand.each do |op|
+ cl = ArvadosModel::kind_class op
+ if cl
+ cond << "#{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
+ end
+ if @where.is_a? Hash and @where.any?
+ conditions = ['1=1']
+ @where.each do |attr,value|
+ if attr.to_s == 'any'
+ if value.is_a?(Array) and
+ value.length == 2 and
+ value[0] == 'contains' then
+ ilikes = []
+ model_class.searchable_columns('ilike').each do |column|
+ ilikes << "#{table_name}.#{column} ilike ?"
+ conditions << "%#{value[1]}%"
+ end
+ if ilikes.any?
+ conditions[0] << ' and (' + ilikes.join(' or ') + ')'
+ end
+ end
+ elsif attr.to_s.match(/^[a-z][_a-z0-9]+$/) and
+ model_class.columns.collect(&:name).index(attr.to_s)
+ if value.nil?
+ conditions[0] << " and #{table_name}.#{attr} is ?"
+ conditions << nil
+ elsif value.is_a? Array
+ if value[0] == 'contains' and value.length == 2
+ conditions[0] << " and #{table_name}.#{attr} like ?"
+ conditions << "%#{value[1]}%"
+ else
+ conditions[0] << " and #{table_name}.#{attr} in (?)"
+ conditions << value
+ end
+ elsif value.is_a? String or value.is_a? Fixnum or value == true or value == false
+ conditions[0] << " and #{table_name}.#{attr}=?"
+ conditions << value
+ elsif value.is_a? Hash
+ # Not quite the same thing as "equal?" but better than nothing?
+ value.each do |k,v|
+ if v.is_a? String
+ conditions[0] << " and #{table_name}.#{attr} ilike ?"
+ conditions << "%#{k}%#{v}%"
+ end
+ end
+ end
+ end
+ end
+ if conditions.length > 1
+ conditions[0].sub!(/^1=1 and /, '')
+ @objects = @objects.
+ where(*conditions)
+ end
+ end
+
+ if params[:limit]
+ begin
+ @limit = params[:limit].to_i
+ rescue
+ raise ArgumentError.new("Invalid value for limit parameter")
+ end
+ else
+ @limit = 100
+ end
+ @objects = @objects.limit(@limit)
+
+ orders = []
+
+ if params[:offset]
+ begin
+ @objects = @objects.offset(params[:offset].to_i)
+ @offset = params[:offset].to_i
+ rescue
+ raise ArgumentError.new("Invalid value for limit parameter")
+ end
+ 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
+ @objects = @objects.order(orders.join ", ")
+ end
+
+end
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list