[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