X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/63f9b5374e01394486a07dba4f9a43cfd76707e3..14ea55f217bbd7061fafc1fe69f4f453ad7c3e59:/apps/workbench/app/models/arvados_base.rb diff --git a/apps/workbench/app/models/arvados_base.rb b/apps/workbench/app/models/arvados_base.rb index 267a4a9133..43f40d9f96 100644 --- a/apps/workbench/app/models/arvados_base.rb +++ b/apps/workbench/app/models/arvados_base.rb @@ -3,21 +3,22 @@ class ArvadosBase < ActiveRecord::Base attr_accessor :attribute_sortkey def self.uuid_infix_object_kind - @@uuid_infix_object_kind ||= { - '4zz18' => 'arvados#collection', - 'tpzed' => 'arvados#user', - 'ozdt8' => 'arvados#api_client', - '8i9sb' => 'arvados#job', - 'o0j2j' => 'arvados#link', - '57u5n' => 'arvados#log', - 'j58dm' => 'arvados#specimen', - 'p5p6p' => 'arvados#pipeline_template', - 'mxsvm' => 'arvados#pipeline_template', # legacy Pipeline objects - 'd1hrv' => 'arvados#pipeline_instance', - 'uo14g' => 'arvados#pipeline_instance', # legacy PipelineInstance objects - 'j7d0g' => 'arvados#group', - 'ldvyl' => 'arvados#group' # only needed for legacy Project objects - } + @@uuid_infix_object_kind ||= + begin + infix_kind = {} + $arvados_api_client.discovery[:schemas].each do |name, schema| + if schema[:uuidPrefix] + infix_kind[schema[:uuidPrefix]] = + 'arvados#' + name.to_s.camelcase(:lower) + end + end + + # Recognize obsolete types. + infix_kind. + merge('mxsvm' => 'arvados#pipelineTemplate', # Pipeline + 'uo14g' => 'arvados#pipelineInstance', # PipelineInvocation + 'ldvyl' => 'arvados#group') # Project + end end def initialize(*args) @@ -25,11 +26,11 @@ class ArvadosBase < ActiveRecord::Base @attribute_sortkey ||= { 'id' => nil, 'uuid' => '000', - 'owner' => '001', + 'owner_uuid' => '001', 'created_at' => '002', 'modified_at' => '003', - 'modified_by_user' => '004', - 'modified_by_client' => '005', + 'modified_by_user_uuid' => '004', + 'modified_by_client_uuid' => '005', 'name' => '050', 'tail_kind' => '100', 'tail_uuid' => '100', @@ -44,47 +45,74 @@ class ArvadosBase < ActiveRecord::Base return @columns unless @columns.nil? @columns = [] @attribute_info ||= {} - return @columns if $arvados_api_client.arvados_schema[self.to_s.to_sym].nil? - $arvados_api_client.arvados_schema[self.to_s.to_sym].each do |coldef| - k = coldef[:name].to_sym - if coldef[:type] == coldef[:type].downcase - @columns << column(k, coldef[:type].to_sym) + schema = $arvados_api_client.discovery[:schemas][self.to_s.to_sym] + return @columns if schema.nil? + schema[:properties].each do |k, coldef| + case k + when :etag, :kind + attr_reader k else - @columns << column(k, :text) - serialize k, coldef[:type].constantize + if coldef[:type] == coldef[:type].downcase + # boolean, integer, etc. + @columns << column(k, coldef[:type].to_sym) + else + # Hash, Array + @columns << column(k, :text) + serialize k, coldef[:type].constantize + end + attr_accessible k + @attribute_info[k] = coldef end - attr_accessible k - @attribute_info[k] = coldef end - attr_reader :etag - attr_reader :kind @columns end + def self.column(name, sql_type = nil, default = nil, null = true) ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null) end + def self.attribute_info self.columns @attribute_info end - def self.find(uuid) + + def self.find(uuid, opts={}) if uuid.class != String or uuid.length < 27 then raise 'argument to find() must be a uuid string. Acceptable formats: warehouse locator or string with format xxxxx-xxxxx-xxxxxxxxxxxxxxx' end - new.private_reload(uuid) + + # Only do one lookup on the API side per {class, uuid, workbench + # request} unless {cache: false} is given via opts. + cache_key = "request_#{Thread.current.object_id}_#{self.to_s}_#{uuid}" + if opts[:cache] == false + Rails.cache.write cache_key, $arvados_api_client.api(self, '/' + uuid) + end + hash = Rails.cache.fetch cache_key do + $arvados_api_client.api(self, '/' + uuid) + end + new.private_reload(hash) + end + + def self.order(*args) + ArvadosResourceList.new(self).order(*args) end + def self.where(*args) ArvadosResourceList.new(self).where(*args) end + def self.limit(*args) ArvadosResourceList.new(self).limit(*args) end + def self.eager(*args) ArvadosResourceList.new(self).eager(*args) end + def self.all(*args) ArvadosResourceList.new(self).all(*args) end + def save obdata = {} self.class.columns.each do |col| @@ -106,14 +134,19 @@ class ArvadosBase < ActiveRecord::Base @kind = resp[:kind] # these attrs can be modified by "save" -- we should update our copies - %w(uuid owner created_at - modified_at modified_by_user modified_by_client + %w(uuid owner_uuid created_at + modified_at modified_by_user_uuid modified_by_client_uuid ).each do |attr| - self.send(attr + '=', resp[attr.to_sym]) + if self.respond_to? "#{attr}=".to_sym + self.send(attr + '=', resp[attr.to_sym]) + end end + @new_record = false + self end + def save! self.save or raise Exception.new("Save failed") end @@ -153,6 +186,7 @@ class ArvadosBase < ActiveRecord::Base @links = $arvados_api_client.api Link, '', { _method: 'GET', where: o, eager: true } @links = $arvados_api_client.unpack_api_response(@links) end + def all_links return @all_links if @all_links res = $arvados_api_client.api Link, '', { @@ -165,9 +199,11 @@ class ArvadosBase < ActiveRecord::Base } @all_links = $arvados_api_client.unpack_api_response(res) end + def reload private_reload(self.uuid) end + def private_reload(uuid_or_hash) raise "No such object" if !uuid_or_hash if uuid_or_hash.is_a? Hash @@ -190,8 +226,14 @@ class ArvadosBase < ActiveRecord::Base end end @all_links = nil + @new_record = false self end + + def to_param + uuid + end + def dup super.forget_uuid! end @@ -209,18 +251,20 @@ class ArvadosBase < ActiveRecord::Base end def editable? - (current_user and + (current_user and current_user.is_active and (current_user.is_admin or - current_user.uuid == self.owner)) + current_user.uuid == self.owner_uuid)) end def attribute_editable?(attr) - if "created_at modified_at modified_by_user modified_by_client updated_at".index(attr.to_s) + if "created_at modified_at modified_by_user_uuid modified_by_client_uuid updated_at".index(attr.to_s) + false + elsif not (current_user.andand.is_active) false - elsif "uuid owner".index(attr.to_s) - current_user and current_user.is_admin + elsif "uuid owner_uuid".index(attr.to_s) or current_user.is_admin + current_user.is_admin else - current_user and current_user.uuid == owner + current_user.uuid == self.owner_uuid or current_user.uuid == self.uuid end end @@ -253,6 +297,14 @@ class ArvadosBase < ActiveRecord::Base resource_class end + def friendly_link_name + (name if self.respond_to? :name) || uuid + end + + def selection_label + friendly_link_name + end + protected def forget_uuid!