Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice for limiting the number of associations within a has_many relationship?

Say that I have two models- Users and Accounts. Each account can have at most n users associated with it, and a user can only be associated with one account.

It would seem natural to say that User

belongs_to :account

and Account

has_many :users

However, I'm not clear on the best practice when it comes to limiting the number of associations through that has_many declaration. I know that there is a :limit argument, but that that only limits the number of associations returned, not the number that are able to exist.

I suspect that the answer is to use something like :before_add. However, that approach seems only to apply to associations created via << . So it would get called when you used

@account.users << someuser 

but not if you used

@account.users.create

I had also considered that it might be more practical to implement the limit using before_save within the User model, but it seems like it would be a bit off to implement Account business rules within the User model.

What is the best practice for limiting the number of associations?

Edit: the n users per account would be some business data that is stored within the individual accounts, rather than being a straight up magic number that would be floating around willy nilly in the code.

like image 302
Eliza Brock Marcum Avatar asked Mar 01 '23 04:03

Eliza Brock Marcum


2 Answers

At first, if your users table has foreign key account_id then you need to use

class User
  belongs_to :account
end

In this way you will ensure that User can be associated just to one Account.

If you want to limit that Account can have e.g. at most 3 users then you can define the following validation:

class User
  validates_each :account do |user, attr, value|
    user.errors.add attr, "too much users for account" if user.account.users.size >= 3
  end
end

and as a result you will not be able to create new user for account if account has already 3 users.

like image 141
Raimonds Simanovskis Avatar answered Mar 03 '23 17:03

Raimonds Simanovskis


I think your rule is subject to a different interpretation. Think of the rule as being "You cannot add a user to an account that already has 3 users." Now that it is a user rule, implementing it on the user object seems perfectly natural and @Raimond's solution will suffice.

You could also think about implementing this as a database constraint, but I probably wouldn't go that way...3 seems to be an arbitrary number that may change later and I, and I suspect you, would prefer that it be captured in the code rather than hidden away in a DB constraint.

like image 33
tvanfosson Avatar answered Mar 03 '23 18:03

tvanfosson