add controller-specific routes to discovery doc
authorTom Clegg <tom@clinicalfuture.com>
Thu, 25 Apr 2013 18:31:15 +0000 (11:31 -0700)
committerTom Clegg <tom@clinicalfuture.com>
Thu, 25 Apr 2013 20:40:27 +0000 (13:40 -0700)
services/api/app/controllers/application_controller.rb
services/api/app/controllers/arvados/v1/nodes_controller.rb
services/api/app/controllers/arvados/v1/schema_controller.rb

index fb4c7adfbd98e435c126415764daac3a4fa7ba99..2e8a11447ca2b92a1868b2abd8c7b25af3d6b169 100644 (file)
@@ -14,6 +14,38 @@ class ApplicationController < ActionController::Base
 
   attr_accessor :resource_attrs
 
+  def index
+    @objects.uniq!(&:id)
+    if params[:eager] and params[:eager] != '0' and params[:eager] != 0 and params[:eager] != ''
+      @objects.each(&:eager_load_associations)
+    end
+    render_list
+  end
+
+  def show
+    if @object
+      render json: @object.as_api_response(:superuser)
+    else
+      render_not_found("object not found")
+    end
+  end
+
+  def create
+    @object = model_class.new resource_attrs
+    @object.save
+    show
+  end
+
+  def update
+    @object.update_attributes resource_attrs
+    show
+  end
+
+  def destroy
+    @object.destroy
+    show
+  end
+
   def catch_redirect_hint
     if !current_user
       if params.has_key?('redirect_to') then
@@ -51,6 +83,8 @@ class ApplicationController < ActionController::Base
     render json: { errors: ["Path not found"] }, status: 404
   end
 
+  protected
+
   def find_objects_for_index
     uuid_list = [current_user.uuid, *current_user.groups_i_can(:read)]
     sanitized_uuid_list = uuid_list.
@@ -109,40 +143,6 @@ class ApplicationController < ActionController::Base
     @objects = @objects.order("#{table_name}.modified_at desc")
   end
 
-  def index
-    @objects.uniq!(&:id)
-    if params[:eager] and params[:eager] != '0' and params[:eager] != 0 and params[:eager] != ''
-      @objects.each(&:eager_load_associations)
-    end
-    render_list
-  end
-
-  def show
-    if @object
-      render json: @object.as_api_response(:superuser)
-    else
-      render_not_found("object not found")
-    end
-  end
-
-  def create
-    @object = model_class.new resource_attrs
-    @object.save
-    show
-  end
-
-  def update
-    @object.update_attributes resource_attrs
-    show
-  end
-
-  def destroy
-    @object.destroy
-    show
-  end
-
-  protected
-
   def resource_attrs
     return @attrs if @attrs
     @attrs = params[resource_name]
@@ -254,7 +254,6 @@ class ApplicationController < ActionController::Base
   def uncamelcase_params_hash_keys
     self.params = uncamelcase_hash_keys(params)
   end
-
   def uncamelcase_hash_keys(h, max_depth=-1)
     if h.is_a? Hash and max_depth != 0
       nh = Hash.new
index 67a5fab6ad75185a023dd7e2d06e19495ae5a053..52f8e9da5e956a4f781d9ef54b569d84ddc2a626 100644 (file)
@@ -8,6 +8,9 @@ class Arvados::V1::NodesController < ApplicationController
     show
   end
 
+  def self._ping_requires_parameters
+    { ping_secret: true }
+  end
   def ping
     @object.ping({ ip: params[:local_ipv4] || request.env['REMOTE_ADDR'],
                    ping_secret: params[:ping_secret],
index ee268654044ec29bb3d202ceacffc3e1c76ccff3..94b9a3cb6506b68649368dbb9d4bd8f45e9c4b9a 100644 (file)
@@ -89,6 +89,12 @@ class Arvados::V1::SchemaController < ApplicationController
       ActiveRecord::Base.descendants.reject(&:abstract_class?).each do |k|
         next if k == ApiClientAuthorization
         next if k == ApiClient
+        begin
+          ctl_class = "Arvados::V1::#{k.to_s.pluralize}Controller".constantize
+        rescue
+          # No controller -> no discovery.
+          next
+        end
         object_properties = {}
         k.columns.
           select { |col| col.name != 'id' }.
@@ -286,6 +292,57 @@ class Arvados::V1::SchemaController < ApplicationController
             }
           }
         }
+        # Check for Rails routes that don't match the usual actions
+        # listed above
+        d_methods = discovery[:resources][k.to_s.underscore.pluralize][:methods]
+        Rails.application.routes.routes.each do |route|
+          action = route.defaults[:action]
+          httpMethod = (route.verb && route.verb.length > 0) ? route.verb : 'GET'
+          if route.defaults[:controller] == 'arvados/v1/' + k.to_s.underscore.pluralize and
+              !d_methods[action.to_sym] and
+              ctl_class.action_methods.include? action
+            method = {
+              id: "arvados.#{k.to_s.underscore.pluralize}.#{action}",
+              path: route.path.sub('/arvados/v1/','').sub('(.:format)','').sub(/:(uu?)id/,'{uuid}'),
+              httpMethod: httpMethod,
+              description: "#{route.defaults[:action]} #{k.to_s.underscore.pluralize}",
+              parameters: {},
+              response: {
+                "$ref" => k.to_s
+              },
+              scopes: [
+                       "https://api.clinicalfuture.com/auth/arvados"
+                      ]
+            }
+            route.segment_keys.each do |key|
+              if key != :format
+                key = :uuid if key == :id
+                method[:parameters][key] = {
+                  type: "string",
+                  description: "",
+                  required: true,
+                  location: "path"
+                }
+              end
+            end
+            if ctl_class.respond_to? "_#{action}_requires_parameters".to_sym
+              ctl_class.send("_#{action}_requires_parameters".to_sym).each do |k, v|
+                if v.is_a? Hash
+                  method[:parameters][k] = v
+                else
+                  method[:parameters][k] = {}
+                end
+                method[:parameters][k][:type] ||= 'string'
+                method[:parameters][k][:description] ||= ''
+                method[:parameters][k][:location] = (route.segment_keys.include?(k) ? 'path' : 'query')
+                if method[:parameters][k][:required].nil?
+                  method[:parameters][k][:required] = v != false
+                end
+              end
+            end
+            d_methods[route.defaults[:action].to_sym] = method
+          end
+        end
       end
       discovery
     end