diff --git a/app/models/object_manager/attribute.rb b/app/models/object_manager/attribute.rb index d348379ac..d5ba71558 100644 --- a/app/models/object_manager/attribute.rb +++ b/app/models/object_manager/attribute.rb @@ -898,6 +898,13 @@ is certain attribute used by triggers, overviews or schedulers reserved_words = %w[destroy true false integer select drop create alter index table varchar blob date datetime timestamp] raise "#{name} is a reserved word, please choose a different one" if name.match?(/^(#{reserved_words.join('|')})$/) + # fixes issue #2236 - Naming an attribute "attribute" causes ActiveRecord failure + begin + ObjectLookup.by_id(object_lookup_id).constantize.instance_method_already_implemented? name + rescue ActiveRecord::DangerousAttributeError => e + raise "#{name} is a reserved word, please choose a different one" + end + record = object_lookup.name.constantize.new return true if !record.respond_to?(name.to_sym) raise "#{name} already exists!" if record.attributes.key?(name) && new_record? diff --git a/spec/models/object_manager/attribute_spec.rb b/spec/models/object_manager/attribute_spec.rb index 6f7b285e7..2153f2c2c 100644 --- a/spec/models/object_manager/attribute_spec.rb +++ b/spec/models/object_manager/attribute_spec.rb @@ -49,4 +49,51 @@ RSpec.describe ObjectManager::Attribute, type: :model do end end end + + describe 'check name' do + it 'rejects ActiveRecord reserved word "attribute"' do + expect do + ObjectManager::Attribute.add attributes_for :object_manager_attribute_text, name: 'attribute' + end.to raise_error 'attribute is a reserved word, please choose a different one' + end + + it 'rejects Zammad reserved word "table"' do + expect do + ObjectManager::Attribute.add attributes_for :object_manager_attribute_text, name: 'table' + end.to raise_error 'table is a reserved word, please choose a different one' + end + + it 'rejects duplicate attribute name of conflicting types' do + attribute = attributes_for :object_manager_attribute_text + ObjectManager::Attribute.add attribute + attribute[:data_type] = 'boolean' + expect do + ObjectManager::Attribute.add attribute + end.to raise_error ActiveRecord::RecordInvalid + end + + it 'accepts duplicate attribute name on the same types (editing an existing attribute)' do + attribute = attributes_for :object_manager_attribute_text + ObjectManager::Attribute.add attribute + expect do + ObjectManager::Attribute.add attribute + end.to_not raise_error + end + + it 'accepts duplicate attribute name on compatible types (editing the type of an existing attribute)' do + attribute = attributes_for :object_manager_attribute_text + ObjectManager::Attribute.add attribute + attribute[:data_type] = 'select' + attribute[:data_option_new] = { default: '', options: { 'a' => 'a' } } + expect do + ObjectManager::Attribute.add attribute + end.to_not raise_error + end + + it 'accepts valid attribute names' do + expect do + ObjectManager::Attribute.add attributes_for :object_manager_attribute_text + end.to_not raise_error + end + end end