【问题标题】:What is the best way of preventing the last record in a has_many collection being removed?防止 has_many 集合中最后一条记录被删除的最佳方法是什么?
【发布时间】:2010-11-09 23:42:04
【问题描述】:

我有两个 ActiveRecord 类。这些类的简化视图:

class Account < ActiveRecord::Base
  has_many :user_account_roles
end

class UserAccountRole < ActiveRecord::Base
  belongs_to :account

  # Has a boolean attribute called 'administrator'.
end

我正在苦苦挣扎的是,我希望能够对此应用两个验证规则: * 确保最后一个 UserAccountRole 不能被删除。 * 确保不能删除作为管理员的最后一个 UserAccountRole。

我真的很难理解实现这种结构验证的最佳方法。我已经尝试向关联添加一个 before_remove 回调,但我不喜欢这必须抛出一个需要被控制器捕获的错误。我宁愿这被视为“只是另一个验证”。

class Account < ActiveRecord::Base
  has_many :user_account_roles, :before_remove => check_remove_role_ok

  def check_remove_relationship_ok(relationship)
    if self.user_account_relationships.size == 1
      errors[:base] << "Cannot remove the last user from this account."
      raise RuntimeError, "Cannot remove the last user from this account."
    end
  end

end

我不认为这有什么不同,但我也在使用accepts_nested_attributes_for。

【问题讨论】:

    标签: ruby-on-rails validation activerecord ruby-on-rails-3


    【解决方案1】:

    为什么不对帐户使用简单的验证?

    class Account < ActiveRecord::Base
      has_many :user_account_roles
    
      validate :at_least_one_user_account_role
      validate :at_least_one_administrator_role
    
      private
      def at_least_one_user_account_role
        if user_account_roles.size < 1
          errors.add_to_base('At least one role must be assigned.')
        end
      end
    
      def at_least_one_administrator_role
        if user_account_roles.none?(&:administrator?)
          errors.add_to_base('At least one administrator role must be assigned.')
        end
      end
    end
    

    这种方式不需要提出任何内容,并且除非有至少一个角色和至少一个管理员角色,否则不会保存记录。因此,当您重新呈现错误的编辑表单时,将显示此消息。

    【讨论】:

    • 好吧,简直不敢相信这就是这么简单!认为 Rails 不够聪明,无法自动管理。我确实必须将验证设置为仅在更新而不是创建时触发,否则实际上首先创建关系会变得很棘手。除此之外,似乎工作正常 :) 谢谢!
    • P.S.必须按如下方式调整“at_least_one_user_account_role”,以使验证规则在保存记录之前在验证中发现这一点:如果 user_account_relationships.size
    【解决方案2】:

    您可以将验证放在 UserAccountRole 上。如果是唯一与 Account 关联的 UserAccountRole,则无法删除。

    一个更简单的解决方案可能是质疑您设计的基本假设。为什么 UserAccountRole 是支持 AR 的模型?为什么不把它变成一个普通的 ruby​​ 类呢?最终用户会动态定义角色吗?如果没有,那么您可以通过将其设为常规 ruby​​ 类来大大简化您的困境。

    【讨论】:

      猜你喜欢
      • 2021-04-10
      • 1970-01-01
      • 1970-01-01
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多