Rails/PostgreSQL - 如何验证哪里只能有两个用户ID的组合?

问题描述:

我尝试创建聊天加入表时遇到问题。它有两个user_id,user_id1和user_id2。当user_id1为1且user_id2为2时,我可以获得唯一性验证;用这些确切的属性不能再创建聊天。但是我正在执行一次匹配搜索,所以有时匹配出现在user_id1为2和user_id2为1的地方,这是一个问题。Rails/PostgreSQL - 如何验证哪里只能有两个用户ID的组合?

我一直在搜索这两个数据库级别之间的唯一性约束,我似乎无法找到任何。我认为对于模型级别,我必须创建一个自定义验证,我可以弄清楚,但是有没有办法在数据库级别执行此操作?或者有更好的方法来解决这个问题吗?提前致谢。

TL; DR:

A = 1,B = 2

我需要B = 1,一个约束= 2

+0

我认为这应该工作。在你的模型'validates:user_id1,uniqueness:{scope::user_id2}',并且这在你的迁移中't.index [:user_id1,:user_id2],unique:true,name:'index_user_id1_and_user_id2'。迁移应该为您的表添加唯一性约束。 – user3366016

+0

感谢您的快速回复。这就是我现在拥有的。现在它确实增加了对货币对唯一性的约束,但不是对中的组合。正如在那里不能有其他的user_id1:1,user_id2:2对。但仍然可以是user_id1:2,user_id2:1对,这是我试图限制的。 –

+0

没有意识到它只走了1路(idX和idY)也不是相反。你可以在迁移中添加第二个约束吗? 't.index [:user_id2,:user_id1],unique:true,name:'index_user_id2_and_user_id1''那么你会有两个? – user3366016

usual way要做到这一点是create an index on an expression和使用greatest and least函数用于构建忽略列顺序的表达式。在你的情况,你需要一个这样的指标:

create unique index whatever_you_want_to_call_it 
on your_table(greatest(user_id1, user_id2), least(user_id1, user_id2)) 

我不知道有什么方法可以让ActiveRecord的构建这样一个指标,也不会被保存在schema.rb。解决这些问题的方法是切换到SQL模式并在迁移中手动创建索引。从db/schema.rb切换到db/structure.sql,在config/application.rb更新设置:

config.active_record.schema_format = :sql 

,然后在迁移创建索引:

def up 
    connection.execute(%q{ 
    create unique index whatever_you_want_to_call_it 
    on your_table(greatest(user_id1, user_id2), least(user_id1, user_id2)) 
    }) 
end 

然后,你可以扔掉你的db/schema.rb(因为它不再是使用)并开始使用db/structure.sql来代替。您还需要开始使用不同的rake任务:

  • db:structure:dump而不是db:schema:dump
  • db:structure:load,而不是db:schema:load