+module ApiTemplateOverride
+ def allowed_to_render?(fieldset, field, model, options)
+ if options[:select]
+ return options[:select].include? field.to_s
+ end
+ super
+ end
+end
+
+class ActsAsApi::ApiTemplate
+ prepend ApiTemplateOverride
+end
+
require 'load_param'
require 'record_filters'
ERROR_ACTIONS = [:render_error, :render_not_found]
+
respond_to :json
protect_from_forgery
attr_accessor :resource_attrs
def index
- @objects.uniq!(&:id)
+ @objects.uniq!(&:id) if @select.nil? or @select.include? "id"
if params[:eager] and params[:eager] != '0' and params[:eager] != 0 and params[:eager] != ''
@objects.each(&:eager_load_associations)
end
end
end
+ @objects = @objects.select(@select.map { |s| "#{table_name}.#{ActiveRecord::Base.connection.quote_column_name s.to_s}" }.join ", ") if @select
+ @objects = @objects.uniq(ActiveRecord::Base.connection.quote_column_name @distinct.to_s) if @distinct
@objects = @objects.order(@orders.join ", ") if @orders.any?
@objects = @objects.limit(@limit)
@objects = @objects.offset(@offset)
:self_link => "",
:offset => @offset,
:limit => @limit,
- :items => @objects.as_api_response(nil)
+ :items => @objects.as_api_response(nil, {select: @select})
}
if @objects.respond_to? :except
@object_list[:items_available] = @objects.
type: "string",
description: "Order in which to return matching #{k.to_s.underscore.pluralize}.",
location: "query"
+ },
+ select: {
+ type: "array",
+ description: "Select which fields to return",
+ location: "query"
+ },
+ distinct: {
+ type: "string",
+ description: "Return each distinct value exactly once for the specified column (may skip rows)",
+ location: "query"
}
},
response: {
if @orders.empty?
@orders << default_orders
end
+
+ case params[:select]
+ when Array
+ @select = params[:select]
+ when String
+ begin
+ @select = Oj.load params[:select]
+ raise unless @select.is_a? Array
+ rescue
+ raise ArgumentError.new("Could not parse \"select\" param as an array")
+ end
+ end
+
+ if params[:distinct].is_a? String
+ @distinct = params[:distinct]
+ @orders.select! { |o| @select.include? o } if @select
+ end
end
--- /dev/null
+require 'test_helper'
+
+class SelectTest < ActionDispatch::IntegrationTest
+ test "should select just two columns" do
+ get "/arvados/v1/links", {:format => :json, :select => ['uuid', 'link_class']}, auth(:active)
+ assert_response :success
+ assert_equal json_response['items'].count, json_response['items'].select { |i|
+ i['uuid'] != nil and i['link_class'] != nil and i['head_uuid'] == nil and i['tail_uuid'] == nil
+ }.count
+ end
+
+ test "should only get distinct values" do
+ get "/arvados/v1/links", {:format => :json, :select => ['link_class'], :distinct => "link_class"}, auth(:active)
+ assert_response :success
+ assert_equal json_response['items'].uniq.count, json_response['items'].count
+ end
+
+end