From: Lucas Di Pentima Date: Tue, 2 Apr 2019 21:36:08 +0000 (-0300) Subject: 14873: Custom JSON attributes that default to [] or {} when nil. X-Git-Tag: 1.4.0~74^2~13 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/33021029867be4a2240f0d3673045dfac7598350 14873: Custom JSON attributes that default to [] or {} when nil. Previously we used the 'serialize' call to declare a JSONB column as a Hash or Array and this had the side effect to default to an empty hash or array when assigning nil (whether was reading from the database or passed as a param). JSONB columns shouldn't be now declared as serialized because Rails would serialize their contents twice, but not declaring them makes us lose their side effect. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- diff --git a/services/api/app/models/collection.rb b/services/api/app/models/collection.rb index cb23df1c21..e6d8d86552 100644 --- a/services/api/app/models/collection.rb +++ b/services/api/app/models/collection.rb @@ -16,8 +16,10 @@ class Collection < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :properties, :jsonbHash, default: {} + attribute :storage_classes_desired, :jsonbArray, default: ["default"] + attribute :storage_classes_confirmed, :jsonbArray, default: [] - before_validation :fill_field_defaults before_validation :default_empty_manifest before_validation :default_storage_classes, on: :create before_validation :check_encoding @@ -653,10 +655,4 @@ class Collection < ArvadosModel self.current_version_uuid ||= self.uuid true end - - def fill_field_defaults - self.properties ||= {} - self.storage_classes_desired ||= [] - self.storage_classes_confirmed ||= [] - end end diff --git a/services/api/app/models/container.rb b/services/api/app/models/container.rb index b02989457e..fb900a993d 100644 --- a/services/api/app/models/container.rb +++ b/services/api/app/models/container.rb @@ -19,6 +19,10 @@ class Container < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :secret_mounts, :jsonbHash, default: {} + attribute :runtime_status, :jsonbHash, default: {} + attribute :runtime_auth_scopes, :jsonbHash, default: {} + serialize :environment, Hash serialize :mounts, Hash serialize :runtime_constraints, Hash diff --git a/services/api/app/models/container_request.rb b/services/api/app/models/container_request.rb index 80e1bf3ffe..292decafbf 100644 --- a/services/api/app/models/container_request.rb +++ b/services/api/app/models/container_request.rb @@ -21,6 +21,9 @@ class ContainerRequest < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :properties, :jsonbHash, default: {} + attribute :secret_mounts, :jsonbHash, default: {} + serialize :environment, Hash serialize :mounts, Hash serialize :runtime_constraints, Hash diff --git a/services/api/app/models/group.rb b/services/api/app/models/group.rb index b63d0ae2af..7fb8fef42b 100644 --- a/services/api/app/models/group.rb +++ b/services/api/app/models/group.rb @@ -14,6 +14,7 @@ class Group < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :properties, :jsonbHash, default: {} after_create :invalidate_permissions_cache after_update :maybe_invalidate_permissions_cache @@ -50,5 +51,4 @@ class Group < ArvadosModel end true end - end diff --git a/services/api/app/models/jsonb_type.rb b/services/api/app/models/jsonb_type.rb new file mode 100644 index 0000000000..2011dcec86 --- /dev/null +++ b/services/api/app/models/jsonb_type.rb @@ -0,0 +1,38 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + +class JsonbType + # Emulate pre-rails5.0 behavior by having a interpreting NULL/nil as + # some other default value. + class WithDefault < ActiveModel::Type::Value + include ActiveModel::Type::Helpers::Mutable + @@default_value = nil + + def deserialize(value) + if value.nil? + @@default_value + elsif value.is_a?(::String) + SafeJSON.load(value) rescue @@default_value + else + value + end + end + + def serialize(value) + if value.nil? + @@default_value + else + SafeJSON.dump(value) + end + end + end + + class Hash < JsonbType::WithDefault + @@default_value = {} + end + + class Array < JsonbType::WithDefault + @@default_value = [] + end +end \ No newline at end of file diff --git a/services/api/app/models/link.rb b/services/api/app/models/link.rb index a95feb83cd..ad7800fe67 100644 --- a/services/api/app/models/link.rb +++ b/services/api/app/models/link.rb @@ -9,6 +9,7 @@ class Link < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :properties, :jsonbHash, default: {} before_create :permission_to_attach_to_objects before_update :permission_to_attach_to_objects @@ -101,5 +102,4 @@ class Link < ArvadosModel super end end - end diff --git a/services/api/app/models/node.rb b/services/api/app/models/node.rb index ecafcdd218..148dffc230 100644 --- a/services/api/app/models/node.rb +++ b/services/api/app/models/node.rb @@ -11,8 +11,9 @@ class Node < ArvadosModel # Posgresql JSONB columns should NOT be declared as serialized, Rails 5 # already know how to properly treat them. + attribute :properties, :jsonbHash, default: {} + attribute :info, :jsonbHash, default: {} - before_validation :fill_field_defaults before_validation :ensure_ping_secret after_update :dns_server_update @@ -141,11 +142,6 @@ class Node < ArvadosModel protected - def fill_field_defaults - self.info ||= {} - self.properties ||= {} - end - def assign_hostname if self.hostname.nil? and Rails.configuration.assign_node_hostname self.hostname = self.class.hostname_for_slot(self.slot_number) diff --git a/services/api/config/initializers/custom_types.rb b/services/api/config/initializers/custom_types.rb new file mode 100644 index 0000000000..aecd4cfd4b --- /dev/null +++ b/services/api/config/initializers/custom_types.rb @@ -0,0 +1,8 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + +# JSONB backed Hash & Array types that default to their empty versions when +# reading NULL from the database, or get nil passed by parameter. +ActiveRecord::Type.register(:jsonbHash, JsonbType::Hash) +ActiveRecord::Type.register(:jsonbArray, JsonbType::Array)