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)
正如文档所说,该方法collection<<(object, \xe2\x80\xa6)
\n\n\n通过将对象的外键设置为集合的主键,将一个或多个对象添加到集合中。请注意,此操作会立即触发更新 SQL,而无需等待对父对象的保存或更新调用,除非父对象是新记录。这还将运行关联对象的验证和回调。
\n
这意味着当您将用户添加到护理团队时,例如
\n\ncare_team.users << user\nRun Code Online (Sandbox Code Playgroud)\n\n用户立即被添加。您不需要调用care_team.save来保存更改。CareTeam不会应用验证。这是因为更改发生在user对象中:其care_team_id属性设置为care_team.id,然后user如果所有验证都通过,则保存 。
CareTeam因此,您可以通过以下方式更改验证来应用限制:
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\nRun Code Online (Sandbox Code Playgroud)\n\n并care_team.save 显式调用以进行验证。然而,它根本没有解决问题:此时用户已经添加到护理团队中。验证将失败,但用户仍留在护理团队中。
要解决该问题,应将验证移至User模型:
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\nRun Code Online (Sandbox Code Playgroud)\n