简体   繁体   中英

Rails has many through relationship

In my Rails app, I have the following models:

class User < ActiveRecord::Base
   # user declaration
   has_many :account
end

class Account < ActiveRecord::Base
   belongs_to :user
end

I need to add another relation where each Account can be managed by multiple AccountManagers . However, AccountManagers themselves are also Users of this system (ie a User can both have an Account and manage another user's account).

I'm fairly new to Rails, and I know that I can just create another model called AccountManagers . I have a feeling that we don't NEED to make another model however; all the information contained within my proposed AccountManagers model is found in the Users model as well.

I've tried to add the following relationship to the Account model:

has_many :account_managers, through: :users, source: :users

where the Account has many managers, and each manager is declared from the User model. This doesn't work as the AccountManagers table doesn't exist (and the error in the view states that as well).

Is there a way to get this relationship to work?

You have to add another join table, say account_managements with columns and user_id and account_id

class User < ActiveRecord::Base
   # user declaration
   has_many :accounts
   has_many :managed_accounts, :source => :account, :through => :account_managements 
end

class Account < ActiveRecord::Base
   belongs_to :user
   has_many :account_managers, :source => :user, :through => :account_managements
end

and

class AccountManagement < ActiveRecord::Base
   belongs_to :user
   belongs_to :account
end

You don't need to add another class AccountManager , You can add one more relation like this:

class User < ActiveRecord::Base
   # user declaration
   has_many :account
   has_many :managed_accounts, :class_name => 'Account', :primary_key => :account_manager_id 
end

class Account < ActiveRecord::Base
   belongs_to :user
   belongs_to :account_managers, : class_name => :User, :foreign_key => :account_manager_id
end

For this you will need to have account_manager_id in the accounts table.

The main issue I can see here is that a user has_many accounts, but in ur example, an account only has 1 user. Are u planning to have accounts with only 1 person in them?

In relational tables there are 2 main kinds of table designs.

A. One to Many

U have a relationship where one thing has many of another thing, for instance: a Owner has many Cats. In this type of relationship the Cat table can point to the Owner table. Clearly the Owner cannot point to its cats because u would need to have a pointer for each cat. it would be something like

Owners table

  • cat_1
  • cat_2
  • cat_3

thats not convenient at all, since there is a maximum number of cats.

If on the other hand u have

cats table

  • owner_id

then each owner can have an unlimited amount of cats.

More complex

After some time u get a request, some owners share a cat. u think about it a while and decide a cat can only belong to a max of 2 owners.

so u change the cat table.

cats table

  • owner_1
  • owner_2

B. Many to Many

If you want to be able to allow a cat to have any unlimited number of owners, or a owner to have an unlimited number of cats, u will need a third table. This table keeps a link from 1 cat to 1 owner. Each row defines this relationship. This table can be named either using the names of the other 2 tables: cat_owners or since this table defines a relationship u can give it a name that defines this relationship.

In this case the relationship is Ownership, people own cats. Its hard to say how the cats would define the relationship :)

This brings me to answer ur question finally. If u have a table that defines the link between a user and an account, I like the name Membership

Membership

  • user_id
  • account_id

but as u just mentioned there are some users in an account who are Managers, u can add this flag to the membership table.

Membership

  • user_id
  • account_id
  • manager (true/false)

u could take it a step beyond that and change manager, to a role column, and then every user can have a different role in every account.

What if each user can have multiple roles in each account? Then u will need more tables

Rails doesnt mean u can skip understanding relational databases structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM