我正在建立一个民意调查网站,我想实现用户(IP地址(每次民意调查可以投票一次。我有以下型号:
class Poll < ApplicationRecord
has_many :answers, :dependent => :destroy
accepts_nested_attributes_for :answers, allow_destroy: true
end
class Answer < ApplicationRecord
belongs_to :poll
has_many :votes
end
class Vote < ApplicationRecord
validates_uniqueness_of :ip_address
belongs_to :answer
end
使用我当前的解决方案,用户可以在一个民意调查中投票一次,然后他不能在另一个民意调查中投票。 我应该使用什么来validates_uniqueness_of :ip_address
每个投票? 我试图通过民意调查使用范围,但它不起作用。
PS:我知道IP地址不是验证唯一投票的最佳解决方案。
您需要作用域的唯一性
validates :ip_address, uniqueness: { scope: :answer_id }
它不允许每个answer
重复ip_address
https://guides.rubyonrails.org/active_record_validations.html#uniqueness
您也可以通过将其添加到迁移中来在数据库级别强制执行它,尽管这是可选的
add_index :votes, [:ip_address, :answer_id], unique: true
但上述解决方案只会防止用户多次不投票支持答案。如果你想poll
唯一性,一种选择是将poll_id
也保存在answers
表中,然后定义唯一性,
或者,第二个选项是在模型中定义自定义验证Vote
validate :uniqueness_with_poll
def uniqueness_with_poll
errors.add(:answer_id, 'already voted for poll') if answer_for_poll_exists?
end
def answer_for_poll_exists?
answer_voted = Vote.where(ip_address: ip_address).pluck(:answer_id)
return false if answer_voted.blank?
answer.poll.answers.where(id: answer_voted).exists?
end
然后定义一个answer_for_poll_exists?
方法来检查民意调查是否已投票,但这可能会很昂贵。
希望对您有所帮助!