Merge branch 'master' into 6203-collection-perf-api
[arvados.git] / apps / workbench / app / models / arvados_base.rb
index f19d47435ae979564c94cf9117109ff44fe5acdf..29379a03ced62b5fad1e782bc08a24ad0c8ba0f3 100644 (file)
@@ -53,6 +53,7 @@ class ArvadosBase < ActiveRecord::Base
       'modified_by_client_uuid' => '203',
       'uuid' => '999',
     }
+    @loaded_attributes = {}
   end
 
   def self.columns
@@ -74,6 +75,14 @@ class ArvadosBase < ActiveRecord::Base
           @columns << column(k, :text)
           serialize k, coldef[:type].constantize
         end
+        define_method k do
+          unless new_record? or @loaded_attributes.include? k.to_s
+            Rails.logger.debug "BUG: access non-loaded attribute #{k}"
+            # We should...
+            # raise ActiveModel::MissingAttributeError, "missing attribute: #{k}"
+          end
+          super()
+        end
         @attribute_info[k] = coldef
       end
     end
@@ -135,6 +144,10 @@ class ArvadosBase < ActiveRecord::Base
     ArvadosResourceList.new(self).select(*args)
   end
 
+  def self.distinct(*args)
+    ArvadosResourceList.new(self).distinct(*args)
+  end
+
   def self.eager(*args)
     ArvadosResourceList.new(self).eager(*args)
   end
@@ -167,8 +180,15 @@ class ArvadosBase < ActiveRecord::Base
   def save
     obdata = {}
     self.class.columns.each do |col|
-      unless self.send(col.name.to_sym).nil? and !self.changed.include?(col.name)
-          obdata[col.name.to_sym] = self.send(col.name.to_sym)
+      # Non-nil serialized values must be sent because we can't tell
+      # whether they've changed. Other than that, any given attribute
+      # is either unchanged (in which case there's no need to send its
+      # old value in the update/create command) or has been added to
+      # #changed by ActiveRecord's #attr= method.
+      if changed.include? col.name or
+          (self.class.serialized_attributes.include? col.name and
+           @loaded_attributes[col.name])
+        obdata[col.name.to_sym] = self.send col.name
       end
     end
     obdata.delete :id
@@ -194,6 +214,7 @@ class ArvadosBase < ActiveRecord::Base
       end
     end
 
+    changes_applied
     @new_record = false
 
     self
@@ -262,6 +283,7 @@ class ArvadosBase < ActiveRecord::Base
       hash = arvados_api_client.api(self.class, '/' + uuid_or_hash)
     end
     hash.each do |k,v|
+      @loaded_attributes[k.to_s] = true
       if self.respond_to?(k.to_s + '=')
         self.send(k.to_s + '=', v)
       else
@@ -276,6 +298,7 @@ class ArvadosBase < ActiveRecord::Base
       end
     end
     @all_links = nil
+    changes_applied
     @new_record = false
     self
   end