【发布时间】:2016-05-25 08:22:39
【问题描述】:
总结:
给定其他四列作为范围,我需要验证两列的唯一性:
validates :preference, uniqueness: { scope: [:voter_id, :term_id, :in_transaction, :transaction_destroy], message: 'must not have the same preference as another vote' }
validates :candidate, uniqueness: { scope: [:voter_id, :term_id, :in_transaction, :transaction_destroy], message: 'can only be voted for once' }
这是为了确保同一选民、同一任期和同一交易状态中只有唯一的偏好和候选人。
问题是,in_transaction 和 transaction_destroy 是布尔值,这意味着 Rails 验证不起作用。
如何编写解决方法?
背景:
我正在开发 STV 选举后端。
整个项目已经完成——前端站点、数据库、结果生成、精美的动画结果差异等。我唯一无法做的就是唯一性验证。
根据 STV 的运作方式,每个选民都可以为任意数量的候选人输入偏好 (int)。如果他们的第一偏好被淘汰,他们的投票将转移到他们的第二偏好,依此类推。所有这些都存储在council_votes 表中,列有voter_id、candidate_id 和preference。
用户也需要能够交换偏好。但是,鉴于偏好唯一性约束,个别更新会破坏验证。为了解决这个问题,并防止网络超时导致数据丢失,我添加了事务。
客户端应用发送begin transaction 消息,发送其偏好更改,最后发送commit 消息。在事务期间,所有更改都会创建带有in_transaction: true 的记录;销毁使用in_transcation: true, transaction_destroy: true 创建记录。提交事务首先会破坏记录,然后使用正确的首选项重新创建记录。如果发生错误,它会回滚更改并通知客户端。
考虑到它的工作原理,基本上有三组“投票”:
- 正常投票
-
in_transaction投票 -
in_transaction && transaction_destroy投票
为了防止重复的候选人/偏好,我必须确保它们在这三个集合中是唯一的。但鉴于两个状态列都是布尔值,我该怎么做?
或者更容易更改架构并将in_transaction 和transaction_destroy 替换为transaction_state (null|create|destroy) 并改为范围?这似乎是一个更明智的选择。
【问题讨论】: