提问人:john bowlee 提问时间:2/18/2023 更新时间:2/18/2023 访问量:121
Ruby on Rails 验证绕过和混淆
Ruby on Rails validation bypass and confusion
问:
我在Ruby on Rails上遇到了一个奇怪的事情,我不知道处理这种情况的正确方法是什么。
我有两个模型,Book 和 Page。
书籍(name:string)
页码(page_number:整数,book_id:ID)
class Book < ActiveRecord::Base
has_many :pages
accepts_nested_attributes_for :pages
end
class Page < ActiveRecord::Base
belongs_to :book
validates_uniqueness_of :page_number, scope: :book_id
end
我创建了一个视图,从中可以更新一本书。我接受页面的嵌套属性,并且有一个部分我可以更新书籍页面以及添加新页面(通过 Javascript 函数,允许用户通过单击 + 按钮添加新的页面行)。正如你所看到的,我有一个验证,要求某本书的页码是唯一的,以防止重复。我还在数据库级别定义了一个唯一的索引(使用 Postgres)
在 Book 的控制器中的更新操作中,我有:
def update
@book = Book.find(params[:id])
if @book.update_attributes(params[:book])
flash[:notice] = 'Book successfully modified!'
end
end
我的方法的问题是,有时绕过了我在 Pages 模型上定义的page_number的验证,我直接从 PG 收到错误(“PG::UniqueViolation: ERROR: duplicate key value violates unique constraint”)。
这种情况发生在 2 种情况下:
- 尝试直接在一个表单提交上创建两个或多个具有相同编号的页面
- 更新现有page_number(例如从 page_number:4 到 nr:5),并在一次表单提交上创建一个数字为 4 的新页面。
似乎存在一些并发性和处理更新/创建的顺序问题。
对于第 2 点,我们应该以某种方式告诉 Rails 查看所有记录,看看我们是否试图通过将更新与创建相结合来进行任何重复。第 2 点是一个有效的选项,应该不会抛出验证错误,但是因为 Rails 首先进行创建,所以它遗憾地发现一个page_number 4 的页面已经存在(没有考虑到page_number 4 正在更新到 5)
我将不胜感激,您可以建议我如何处理这种情况并能够预测所有用例,以便在发生验证错误时我不会访问数据库。
如果这是不可能的,有没有办法从Postgres中捕获错误,格式化并将其显示给用户?
我感谢任何建议!
答: 暂无答案
评论
validates_uniqueness_of
rescue PG::UniqueViolation