Reputation: 87
Hey guys currently working with a couple of models that are associated to each other. The associations are working great, but im trying to limit the amount of users that can belong to the care teams model, ive tried the validate method below and it doesnt seem to raise any error or anything. users can keep adding themselves to that team im trying to limit the amount to. any ideas?
user.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
care-team.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
Upvotes: 2
Views: 2421
Reputation: 2791
As documentation says, the method collection<<(object, …)
Adds one or more objects to the collection by setting their foreign keys to the collection's primary key. Note that this operation instantly fires update SQL without waiting for the save or update call on the parent object, unless the parent object is a new record. This will also run validations and callbacks of associated object(s).
It means that when you add a user to care team, such as
care_team.users << user
the user is added immediately. You don't need to call care_team.save
to save changes. CareTeam
's validation won't be applied. That's because the changes are happening in user
object: its care_team_id
attribute is set to care_team.id
, and then the user
is saved if all its validations pass.
So you could apply your restriction by changing your validation in CareTeam
in this way:
def validate_user_limit
if users.count > NUMBER_OF_PERMITTED_USERS
errors[:base] << "This care team has already enough users"
end
end
and call care_team.save
explicitly to make validation happen. However, it does not fix the problem at all: by that moment user is already added to care team. Validation will fail, but the user remains in the care team.
To fix the problem the validation should be moved to User
model:
class User < ApplicationRecord
validate :validate_care_team_user_limit
private
def validate_care_team_user_limit
if care_team_id && User.where(care_team_id: care_team_id).count >= CareTeam::NUMBER_OF_PERMITTED_USERS
errors.add(:care_team_id, "User cannot be added to that care team")
end
end
end
Upvotes: 5
Reputation: 15838
You souldn't raise exceptions on validations, just add the error if the condition is true:
def validate_user_limit #the (user) param does not go here
self.errors.add(:users, "Too many users") if users.count > NUMBER_OF_PERMITTED_USERS
end
If you want to get an exception with an invalid record then use save!
instead of save
which returns false for invalid records.
Upvotes: 0