提问人:Steven 提问时间:10/12/2017 更新时间:11/17/2023 访问量:204
如何在 Rails 迁移中使用 GREATEST 和 LEAST?
How can I use GREATEST and LEAST in a Rails migration?
问:
我需要确保列和 上的表中的双向唯一性。friendships
requester_id
accepter_id
Table: friendships
requester_id | accepter_id
--------------------------
1 | 2
2 | 1 <-- this should not be possible
作为要考虑的解决方案,我找到了这种方法:Postgresql 强制执行唯一的列双向组合
create unique index ifriendz on friendz(greatest(from_id,to_id), least(from_id,to_id));
我正在尝试编写一个 Rails 迁移(我知道我也可以使用普通 SQL,但我想让它干净)。
这是我重写命令的尝试。这是行不通的。
class AddBidirectionalUniqueConstraintToFriendships < ActiveRecord::Migration
def change
add index :friendships, greatest[:requester_id, :accepter_id], least[:requester_id, :accepter_id], unique: true
end
end
答:
4赞
Rob Di Marco
10/12/2017
#1
您可以使用命令运行任意 SQL 命令。execute
例如:
class AddBidirectionalUniqueConstraintToFriendships < ActiveRecord::Migration
def up
execute <<-SQL
create unique index ifriendz on friendz(greatest(from_id,to_id), least(from_id,to_id));
SQL
end
def down
execute <<-SQL
drop index ifriendz;
SQL
end
end
```
评论
0赞
Steven
10/13/2017
谢谢。考虑到这可能仅适用于 MySQL 和 PostgreSQL,这是否干净?
0赞
mu is too short
10/13/2017
这还不够。 不会包含正确的索引,除非您还切换到 .db/schema.rb
db/structure.sql
0赞
Rob Di Marco
10/13/2017
mu 是正确的,在您的config/application.rb
config.active_record.schema_format = :sql
db/structure.sql
0赞
aaronkelton
11/17/2023
#2
你实际上是在问如何防止双向唯一性。使用 GREATEST 和 LEAST 只是一种方法。相反,您可以编写自定义验证:
class Friendship
validate :bidirectional_uniqueness
def bidirectional_uniqueness
if Friendship.where(requester_id: accepter_id, accepter_id: requester_id).present?
errors.add(:requester_id, "is not bidirectionally unique with accepter_id")
end
end
end
评论
greatest
least