Rails has_many 模型验证

kev*_*pez 2 validation model ruby-on-rails

大家好,目前正在使用几个相互关联的模型。这些协会工作得很好,但我试图限制可以属于护理团队模型的用户数量,我尝试了下面的验证方法,它似乎没有引发任何错误或任何东西。用户可以继续将自己添加到我试图限制数量的团队中。有任何想法吗?

用户.rb

class User < ApplicationRecord
   devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable 
   validates_presence_of :phone, :city, :state, :street, :zip, presence: true, on: :create

   belongs_to :care_team, optional: true
end
Run Code Online (Sandbox Code Playgroud)

护理团队.rb

class CareTeam < ApplicationRecord
   NUMBER_OF_PERMITTED_USERS = 3 

   belongs_to :user, optional: true 

   has_many :users

   validate :validate_user_limit

   private
      def validate_user_limit(user)
         raise Exception.new if users.count > NUMBER_OF_PERMITTED_USERS
      end 
end
Run Code Online (Sandbox Code Playgroud)

Ily*_*hov 5

正如文档所说,该方法collection<<(object, \xe2\x80\xa6)

\n\n
\n

通过将对象的外键设置为集合的主键,将一个或多个对象添加到集合中。请注意,此操作会立即触发更新 SQL,而无需等待对父对象的保存或更新调用,除非父对象是新记录。这还将运行关联对象的验证和回调。

\n
\n\n

这意味着当您将用户添加到护理团队时,例如

\n\n
care_team.users << user\n
Run Code Online (Sandbox Code Playgroud)\n\n

用户立即被添加。您不需要调用care_team.save来保存更改。CareTeam不会应用验证。这是因为更改发生在user对象中:其care_team_id属性设置为care_team.id,然后user如果所有验证都通过,则保存 。

\n\n

CareTeam因此,您可以通过以下方式更改验证来应用限制:

\n\n
def validate_user_limit\n  if users.count > NUMBER_OF_PERMITTED_USERS\n    errors[:base] << "This care team has already enough users"\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

care_team.save 显式调用以进行验证。然而,它根本没有解决问题:此时用户已经添加到护理团队中。验证将失败,但用户仍留在护理团队中。

\n\n

要解决该问题,应将验证移至User模型:

\n\n
class User < ApplicationRecord\n  validate :validate_care_team_user_limit\n\n  private\n\n  def validate_care_team_user_limit\n    if care_team_id && User.where(care_team_id: care_team_id).count >= CareTeam::NUMBER_OF_PERMITTED_USERS\n      errors.add(:care_team_id, "User cannot be added to that care team")\n    end\n  end\nend\n
Run Code Online (Sandbox Code Playgroud)\n