我遇到了一个问题,我认为我的解决方案目前非常难看,有什么更好的方法可以使用rails / mongoid执行以下操作?基本上,用户可以进入并提供'nil'的answer_id,但是一旦他们回答了问题,我们就想锁定他们的第一个非零回答。
controller.rb
r = Response.new(user: current_user, question_id: qid, answer_id: aid)
r.save_now!
以下response.rb模型:
def save_now!
user = self.user
qid = self.question_id
aid = self.answer_id
resp = Response.where({user_id: user._id, question_id: qid}).first
# We accept the first answer that is non-nil,
# so a user can skip the question (answer_id=nil)
# And then return and update the answer_id from nil to 'xyz'
if resp.nil?
resp = Response.new(user: user, question_id: qid, answer_id: aid)
else
if resp.answer_id.nil? && aid.present?
resp.answer_id = aid
end
end
resp.save!
end
所以我想最初允许answer_id为nil(如果用户跳过了问题),然后取第一个非零的答案。
我真的不认为两次实例化Response对象是直观和干净的,一次在控制器中,一次在模型中,但我不确定最好的方法吗?感谢。
答案 0 :(得分:1)
在(user, question_id, answer_id)
上创建唯一索引。这样只有第一个插入才会成功。后续插入将失败并显示错误。这样就无需在find
方法中进行save_now!
查询。
请记住以安全模式运行此插入,否则您将无法获得异常,它将无声地失败。
似乎可以通过重命名方法解决您的问题。 :)看看:
class Response
def self.save_answer(user, qid, aid)
resp = Response.where({user_id: user._id, question_id: qid}).first
if resp.nil?
resp = Response.new(user: user, question_id: qid, answer_id: aid)
else
if resp.answer_id.nil? && aid.present?
resp.answer_id = aid
end
end
resp.save!
end
end
# controller.rb
r = Response.save_answer(current_user, qid, aid)
答案 1 :(得分:-1)
Mongoid对您可以使用的唯一性进行验证。在您的情况下,您可以在user,question_id和answer_id上创建复合索引,并且不需要编写save_answer方法。
例如,您可以将其放在Response模型中:
validates_uniqueness_of :user_id, :question_id
确保每个用户只能对一个问题进行一次回复。