Model Relations in Ruby on Rails

浪尽此生 提交于 2019-12-05 16:40:14

I'm doing something similar with a photo gallery that has shared permissions. Here is roughly the structure I've given it (though this is adapted from another project so may not be exactly right).

class User
  has_many :projects, :foreign_key => "owner_id"
  has_many :project_memberships, :foreign_key => "member_id"
  has_many :shared_projects, :class_name => "Project", :through => :project_memberships, :foreign_key => "member_id"
end

class ProjectMembership
  belongs_to :member, :class_name => 'User'
  belongs_to :project
end

class Project
  belongs_to :owner, :class_name => "User"
  has_many :project_memberships
  has_many :members, :class_name => "User", :through => "project_memberships", :foreign_key => "member_id"
end

Basically, this allows a project to have both an owner that's a user and a bunch of other members that are also users, and they can be accessed separately as such. These are related using a has_many :through relationship, and we're basically giving a more meaningful name than what the default has_many :users would give us.

This also gives individual members the ability to join a project by creating a new project_membership object for said project, while still maintaining a single owner.

Check out this Rails Guide on associations (relationships).

There are a number of ways to set this up each with its own pros and cons. Reading through the guide above should give you a pretty good understanding of the various options available.

You are probably going to end up with a many-to-many association (a project can have many users and a user can have many projects). There you have two main choices: has_and_belongs_to_many or has_many :through. The first is the most "automagic" but the latter offers more control. The latter is my personal preference.

Like I said, read the rails guides so you know what your options are.

So diagramming your model I would expect you have the following:

User --< UserProject >-- Project

This means a user can be associated with many projects and a project can be associated with many users with 1 owner. Your tables would then have:

mysql> desc users;
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| id    | int(11) | NO   | PRI | NULL    | auto_increment |
+-------+---------+------+-----+---------+----------------+

mysql> desc projects;
+-------+---------+------+-----+---------+----------------+
| Field | Type    | Null | Key | Default | Extra          |
+-------+---------+------+-----+---------+----------------+
| id    | int(11) | NO   | PRI | NULL    | auto_increment |
+-------+---------+------+-----+---------+----------------+

mysql> desc user_projects;    
+---------------+---------+------+-----+---------+-------+
| Field         | Type    | Null | Key | Default | Extra |
+---------------+---------+------+-----+---------+-------+
| user_id       | int(11) | YES  |     | NULL    |       |
| project_id    | int(11) | YES  |     | NULL    |       |
| project_owner | int(1)  | YES  |     | NULL    |       |
+---------------+---------+------+-----+---------+-------+

Your models would then look like:

class User < ActiveRecord::Base
  has_many :user_projects
  has_many :projects, :through => :user_projects
end

class UserProjects < ActiveRecord::Base
  belongs_to :users
  belongs_to :projects
end

class Projects < ActiveRecord::Base
  has_many :user_projects
  has_many :users, :through => :user_projects
end

That should be enough to get your started

Sounds like Project model will have both "belongs_to :user" (admin of the project) and "has_many :users" (participants). I have never tried it personally though. At the same time User model will be more complex.

Overall I think it makes more sense to make a "many-to-many" relationship between User and Project and "assign" roles to users (like admin,participant, etc) per project.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!