From 3c3aec40cae849246ab5ded53bc97b2fa547af62 Mon Sep 17 00:00:00 2001 From: Benjamin French Date: Sun, 19 Sep 2021 22:04:53 +0200 Subject: [PATCH 1/3] Filter virtual columns from the attribute names --- activerecord/lib/active_record/attribute_methods.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 3c9f61ec0b..26f2124cb7 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -387,20 +387,22 @@ module ActiveRecord attribute_names.index_with { |name| @attributes[name] } end - # Filters the primary keys and readonly attributes from the attribute names. + # Filters the primary keys, readonly attributes and virtual columns from the attribute names. def attributes_for_update(attribute_names) attribute_names &= self.class.column_names attribute_names.delete_if do |name| - self.class.readonly_attribute?(name) + self.class.readonly_attribute?(name) || + column_for_attribute(name).virtual? end end - # Filters out the primary keys, from the attribute names, when the primary + # Filters out the virtual columns and also primary keys, from the attribute names, when the primary # key is to be generated (e.g. the id attribute has no value). def attributes_for_create(attribute_names) attribute_names &= self.class.column_names attribute_names.delete_if do |name| - pk_attribute?(name) && id.nil? + (pk_attribute?(name) && id.nil?) || + column_for_attribute(name).virtual? end end From e8175f4e235b9b6a0b6fd553d29790e3353dd3f7 Mon Sep 17 00:00:00 2001 From: Benjamin French Date: Sun, 19 Sep 2021 23:55:53 +0200 Subject: [PATCH 2/3] Added a virtual? method for the column base class which always returns false --- activerecord/lib/active_record/connection_adapters/column.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 85521ce9ea..bfff81b91b 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -87,6 +87,10 @@ module ActiveRecord comment.hash end + def virtual? + false + end + private def deduplicated @name = -name From a3a797e30ffb3685c0eb0e2f5b47d8a774bb4161 Mon Sep 17 00:00:00 2001 From: Benjamin French Date: Mon, 20 Sep 2021 10:42:43 +0200 Subject: [PATCH 3/3] Added a test for creating a model with virtual columns and full inserts --- .../cases/adapters/postgresql/virtual_column_test.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/activerecord/test/cases/adapters/postgresql/virtual_column_test.rb b/activerecord/test/cases/adapters/postgresql/virtual_column_test.rb index fa6dcc51a6..069e10e74b 100644 --- a/activerecord/test/cases/adapters/postgresql/virtual_column_test.rb +++ b/activerecord/test/cases/adapters/postgresql/virtual_column_test.rb @@ -23,6 +23,16 @@ if ActiveRecord::Base.connection.supports_virtual_columns? VirtualColumn.create(name: "Rails") end + def test_virtual_column_with_full_inserts + partial_inserts_was = VirtualColumn.partial_inserts + VirtualColumn.partial_inserts = false + assert_nothing_raised do + VirtualColumn.create!(name: "Rails") + end + ensure + VirtualColumn.partial_inserts = partial_inserts_was + end + def teardown @connection.drop_table :virtual_columns, if_exists: true VirtualColumn.reset_column_information