2017-10-12 38 views
1

我需要確保列requester_idaccepter_id上的表friendships內的雙向唯一性。如何在Rails遷移中使用GREATEST和LEAST?

Table: friendships 

requester_id | accepter_id 
-------------------------- 
      1 |   2 
      2 |   1 <-- this should not be possible 

作爲一個解決方案來考慮,我發現這種方法:Postgresql enforce unique two-way combination of columns

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 
+0

我不知道Rails的ActiveRecord的事情,但如果是像大多數其他ORM框架,那麼它很可能僅限於大多ANSI有味SQL功能。 「最大」和「最小」函數是非常特定於數據庫的。 Postgres和MySQL支持它,但不是所有的數據庫。所以你試圖做的事情可能是不可能的。 –

回答

3

您可以使用execute命令運行任意SQL命令。

例如:

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

謝謝。這是乾淨的考慮這可能只適用於MySQL和PostgreSQL? – Steven

+0

這還不夠。 'db/schema.rb'將不包含正確的索引,除非你也切換到'db/structure.sql'。 –

+0

mu是正確的,在你的'config/application.rb'中,你需要設置'config.active_record.schema_format =:sql'來使用'db/structure.sql' –