对has_many属性的Rails验证

时间:2014-12-08 01:10:10

标签: ruby-on-rails ruby

我有CompanyUserDepartment模型。有多个不同的公司,每个公司都有has_many个部门。

User可以通过Departments联接表属于多个UserDepartments

在我User的表单中,我使用:

<%= f.collection_check_boxes :department_ids, @user.company.departments.all, :id, :name %>

验证恶意用户未使用Curl等发布不属于该用户公司的department_id的最佳做法是什么?

我目前在联接表本身上使用以下内容,但我想知道是否有更好的接受做法?

class UserDepartment < ActiveRecord::Base
  belongs_to :user
  belongs_to :department

  validate :check_company_matches

  private
    def check_company_matches 
      unless user.company_id == department.company_id
        errors.add(:user, "This department does not match the user's company.")
      end
    end
end

另外,如果用户确实提交了恶意ID,则rails会显示异常页面,而不是通常的带有errors对象的表单呈现页面;那是为什么?

另一个不足之处是,当您提交用户表单时,如果选中5个不同的部门,则此验证将创建5个SQL查询。据推测,如果用户模型本身进行了验证,则可以使用一个查询完成此操作。当然,数据完整性是我最关心的问题。

感谢。

1 个答案:

答案 0 :(得分:0)

阻止恶意用户卷曲到服务器的事情就是csrf_token,所以Rails正在为你处理这个问题。这可能是您所看到的错误。

我会保持业务逻辑,就像验证它验证的东西一样。连接表不是Thing本身;事实上,它没有东西。

因此,通过将验证移动到User,您可以将逻辑保存在一个位置并避免使用额外的sql。

def ensure_departments_in_company
  company_department_ids = company.departments.pluck(:id)
  unless deparment_ids.map { |id| id.in?(company_department_ids) }.all?
    errors.add(:user, "This department does not match the user's company.")
  end
end