【发布时间】:2015-05-21 21:04:55
【问题描述】:
首先,让我来做个准备:
我有一个app_settings 表,它将app_setting_options 与user_id、user_role_id、event_id、group_id 或app_level_setting 连接起来。对于任何给定的app_setting,应该有一个特定的app_setting_option_id,并且只有一个其他对象。对于这些次要对象中的每一个,我都在AppSetting 模型中指定了一个唯一性验证:
validates :user_id, uniqueness: { scope: :app_setting_option_id}, allow_nil: true
validates :user_role_id, uniqueness: { scope: :app_setting_option_id}, allow_nil: true
validates :group_id, uniqueness: { scope: :app_setting_option_id}, allow_nil: true
validates :event_id, uniqueness: { scope: :app_setting_option_id}, allow_nil: true
validates :app_level_setting, uniqueness: { scope: :app_setting_option_id}, allow_nil: true
除此之外,我还在数据库中的每个辅助对象上设置了一个复合唯一索引。通常我只会依靠 ActiveRecord 验证来处理任何奇怪的边缘情况,但是(长话短说)往往会发生相当多的直接数据库调整,我们希望阻止意外发生。
在我的测试中,我创建了一个带有特定 app_setting_option 和特定 user_id 的 app_setting,然后尝试再次执行完全相同的操作。验证阻止了这种情况的发生。它也可以完美地与user_role、event 和group 配合使用。问题在于app_level_setting,它以某种方式使其通过验证并被数据库级别的复合唯一索引停止,得到Mysql2::Error: Duplicate entry。
it 'app_level_setting uniqueness' do
app_setting_option = AppSettingOption.find(21)
create(:app_setting, app_setting_option: app_setting_option, app_level_setting: 1)
create(:app_setting, app_setting_option: app_setting_option, app_level_setting: 1)
end
第二个 app_setting 没有创建是因为数据库上的索引,而不是因为验证。关于布尔值的唯一性验证有什么具体的吗?当我尝试在控制台中创建相同的 app_level_setting 时,我也遇到了同样的错误。
【问题讨论】:
标签: ruby-on-rails validation activerecord