Ruby on Rails 验证绕过和混淆

问题描述 投票:0回答:0

我在 Ruby on Rails 上遇到了一件奇怪的事情,我不知道处理这种情况的正确方法是什么。

我有两个模型,Book 和 Page。

书(名称:字符串)

Page(page_number: integer, 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个案例上:

  1. 尝试直接创建两个或更多具有相同编号的页面一次提交表格
  2. 更新现有的 page_number(例如从 page_number: 4 到 nr: 5)并创建一个新的页码为 4 on one form submission.

似乎存在一些并发问题和处理更新/创建的顺序。

对于第 2 点,我们应该以某种方式告诉 Rails 查看所有记录,看看我们是否试图通过将更新与创建相结合来进行任何重复。第 2 点是一个有效的选项,应该不会抛出验证错误,但是因为 Rails 首先进行创建,它感叹 page_number 4 的页面已经存在(没有考虑 page_number 4 正在更新为 5)

如果你能建议我如何处理这种情况并能够预测所有用例,我将不胜感激,这样我就不会在验证错误的情况下访问数据库。

如果这是不可能的,有没有办法从 Postgres 捕获错误,格式化并将其显示给用户?

感谢任何建议!

ruby-on-rails ruby validation ruby-on-rails-3
© www.soinside.com 2019 - 2024. All rights reserved.