11168: Always deep-sort before comparing in where_serialized.
[arvados.git] / services / api / app / models / arvados_model.rb
index 910db7e0c7bad2bb0a38ebbc8d0b02a40b63561f..0419dadafba891995156b7f5c286f1955a9fbb8e 100644 (file)
@@ -1,5 +1,6 @@
 require 'has_uuid'
 require 'record_filters'
+require 'serializers'
 
 class ArvadosModel < ActiveRecord::Base
   self.abstract_class = true
@@ -32,7 +33,11 @@ class ArvadosModel < ActiveRecord::Base
   # Note: This only returns permission links. It does not account for
   # permissions obtained via user.is_admin or
   # user.uuid==object.owner_uuid.
-  has_many :permissions, :foreign_key => :head_uuid, :class_name => 'Link', :primary_key => :uuid, :conditions => "link_class = 'permission'"
+  has_many(:permissions,
+           foreign_key: :head_uuid,
+           class_name: 'Link',
+           primary_key: :uuid,
+           conditions: "link_class = 'permission'")
 
   class PermissionDeniedError < StandardError
     def http_status
@@ -450,6 +455,20 @@ class ArvadosModel < ActiveRecord::Base
     end
   end
 
+  def self.where_serialized(colname, value)
+    sorted = deep_sort_hash(value)
+    where("#{colname.to_s} IN (?)", [sorted.to_yaml, SafeJSON.dump(sorted)])
+  end
+
+  Serializer = {
+    Hash => HashSerializer,
+    Array => ArraySerializer,
+  }
+
+  def self.serialize(colname, type)
+    super(colname, Serializer[type])
+  end
+
   def ensure_serialized_attribute_type
     # Specifying a type in the "serialize" declaration causes rails to
     # raise an exception if a different data type is retrieved from
@@ -597,7 +616,7 @@ class ArvadosModel < ActiveRecord::Base
     if self == ArvadosModel
       # If called directly as ArvadosModel.find_by_uuid rather than via subclass,
       # delegate to the appropriate subclass based on the given uuid.
-      self.resource_class_for_uuid(uuid).find_by_uuid(uuid)
+      self.resource_class_for_uuid(uuid).unscoped.find_by_uuid(uuid)
     else
       super
     end