Skip to content

Fix class_attribute shared with parent class

What does this MR do and why?

https://api.rubyonrails.org/classes/Class.html#method-i-class_attribute

This matches normal Ruby method inheritance: think of writing an attribute on a subclass as overriding the reader method. However, you need to be aware when using class_attribute with mutable structures as Array or Hash. In such cases, you don't want to do changes in place. Instead use setters:

Base.setting = []
Base.setting                # => []
Subclass.setting            # => []

# Appending in child changes both parent and child because it is the same object:
Subclass.setting << :foo
Base.setting               # => [:foo]
Subclass.setting           # => [:foo]

# Use setters to not propagate changes:
Base.setting = []
Subclass.setting += [:foo]
Base.setting               # => []
Subclass.setting           # => [:foo]

Screenshots or screen recordings

Before :

[1] pry(main)> WebHook.attributes_exempt_from_serializable_hash
=> [:runners_registration_token,
 "runners_registration_token_encrypted",
 :health_check_access_token,
 :static_objects_external_storage_auth_token,
 "static_objects_external_storage_auth_token_encrypted",
 :incoming_email_token,
 :feed_token,
 :static_object_token,
 "static_object_token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :token,
 "token_expires_at",
 "token_encrypted",
 :token,
 "token_encrypted",
 :token,
 "token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :saml_discovery_token]
[2] pry(main)> User.attributes_exempt_from_serializable_hash
=> [:runners_registration_token,
 "runners_registration_token_encrypted",
 :health_check_access_token,
 :static_objects_external_storage_auth_token,
 "static_objects_external_storage_auth_token_encrypted",
 :incoming_email_token,
 :feed_token,
 :static_object_token,
 "static_object_token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :token,
 "token_expires_at",
 "token_encrypted",
 :token,
 "token_encrypted",
 :token,
 "token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :saml_discovery_token]
[3] pry(main)> Project.attributes_exempt_from_serializable_hash
=> [:runners_registration_token,
 "runners_registration_token_encrypted",
 :health_check_access_token,
 :static_objects_external_storage_auth_token,
 "static_objects_external_storage_auth_token_encrypted",
 :incoming_email_token,
 :feed_token,
 :static_object_token,
 "static_object_token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :token,
 "token_expires_at",
 "token_encrypted",
 :token,
 "token_encrypted",
 :token,
 "token_encrypted",
 :runners_token,
 "runners_token_encrypted",
 :saml_discovery_token]

After:

[1] pry(main)> WebHook.attributes_exempt_from_serializable_hash
=> []
[2] pry(main)> User.attributes_exempt_from_serializable_hash
=> [:incoming_email_token, :feed_token, :static_object_token, "static_object_token_encrypted"]
[3] pry(main)> Project.attributes_exempt_from_serializable_hash
=> [:runners_token, "runners_token_encrypted"]

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

MR acceptance checklist

This checklist encourages us to confirm any changes have been analyzed to reduce risks in quality, performance, reliability, security, and maintainability.

Edited by Thong Kuah

Merge request reports