Rails创建M:M关系

时间:2017-05-22 02:24:22

标签: ruby-on-rails activerecord

我有一个由会员模型加入的用户和团队模型。

一个用户可以拥有多个团队,每个团队可以拥有许多用户等。

class User < ApplicationRecord
  has_many :memberships
  has_many :teams, through: :memberships
End

class Team < ApplicationRecord
  has_many :memberships
  has_many :users, through: :memberships
End

class Membership < ApplicationRecord
  belongs_to :user
  belongs_to :team
end

我正在寻找一种方法来简单地创建一个会员记录但却遗漏了一些东西:

2.4.0 :026 > t = Team.last
  Team Load (1.2ms)  SELECT  "teams".* FROM "teams" ORDER BY "teams"."id" DESC LIMIT $1  [["LIMIT", 1]]
 => #<Team id: 42129, name: "Reds", description: "A good team", created_at: "2017-05-18 05:05:09", updated_at: "2017-05-18 05:05:09"> 
2.4.0 :027 > User.first.memberships
  User Load (1.7ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
  Membership Load (1.1ms)  SELECT  "memberships".* FROM "memberships" WHERE "memberships"."user_id" = $1 LIMIT $2  [["user_id", 1], ["LIMIT", 11]]
 => #<ActiveRecord::Associations::CollectionProxy []> 
2.4.0 :028 > User.first.memberships << t
  User Load (0.8ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
   (0.4ms)  BEGIN
   (0.4ms)  ROLLBACK
ActiveRecord::AssociationTypeMismatch: Membership(#23507760) expected, got #<Team id: 42129, name: "Reds", description: "A good team", created_at: "2017-05-18 05:05:09", updated_at: "2017-05-18 05:05:09"> which is an instance of Team(#33684520)
    from (irb):28
2.4.0 :029 > 

我在这里缺少什么?

更新 当我创建新的成员资格记录并手动添加fk值时,我在尝试保存时收到此错误:

2.4.0 :037 > m
 => #<Membership id: nil, user_id: 1, team_id: 22641, created_at: nil, updated_at: nil> 
2.4.0 :038 > m.save
   (0.5ms)  BEGIN
   (0.4ms)  ROLLBACK
NoMethodError: undefined method `class_name' for nil:NilClass
Did you mean?  class_eval
    from (irb):38

UPDATE2

2.4.0 :022 > user = User.first
  User Load (2.7ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => #<User id: 1, created_at: "2017-05-15 08:17:01", updated_at: "2017-05-19 02:54:30"> 
2.4.0 :023 > team = Team.first
  Team Load (2.3ms)  SELECT  "teams".* FROM "teams" ORDER BY "teams"."id" ASC LIMIT $1  [["LIMIT", 1]]
 => #<Team id: 22641, name: "Reds", description: "This is a good team", created_at: "2017-05-18 01:41:00", updated_at: "2017-05-18 05:05:09"> 

2.4.0 :027 > Membership.delete_all
  SQL (1.9ms)  DELETE FROM "memberships"
 => 1 
2.4.0 :029 > m=Membership.new(user: user, team: team)
 => #<Membership id: nil, user_id: 1, team_id: 22641, created_at: nil, updated_at: nil> 
2.4.0 :031 > m.save
   (1.0ms)  BEGIN
  SQL (2.3ms)  INSERT INTO "memberships" ("user_id", "team_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"  [["user_id", 1], ["team_id", 22641], ["created_at", "2017-05-22 03:37:22.803718"], ["updated_at", "2017-05-22 03:37:22.803718"]]
   (2.1ms)  COMMIT
 => true 

2.4.0 :032 > Membership.delete_all
  SQL (1.9ms)  DELETE FROM "memberships"
 => 1 
2.4.0 :033 > m=Membership.new
 => #<Membership id: nil, user_id: nil, team_id: nil, created_at: nil, updated_at: nil> 
2.4.0 :034 > m.user_id=user.id
 => 1 
2.4.0 :035 > m.team_id=team.id
 => 22641 
2.4.0 :036 > m
 => #<Membership id: nil, user_id: 1, team_id: 22641, created_at: nil, updated_at: nil> 
2.4.0 :037 > m.save
   (0.5ms)  BEGIN
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT $2  [["id", 1], ["LIMIT", 1]]
   (0.8ms)  ROLLBACK
NoMethodError: undefined method `class_name' for nil:NilClass
Did you mean?  class_eval
    from (irb):37

1 个答案:

答案 0 :(得分:1)

您收到的第一条错误消息(在更新之前)是因为ActiveRecord期待Membership的实例,并且它获得了{{1 }}。 Team应该适用于该示例。

就您在更新中分享的错误而言,我在尝试时遇到的情况并没有遇到,而且它似乎与您提供的关系完好无损。

User.first.teams << t

仔细检查的一件事是你如何构建2.2.3 :009 > user = User.first User Load (0.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1 => #<User id: 1> 2.2.3 :010 > team = Team.first Team Load (0.2ms) SELECT "teams".* FROM "teams" ORDER BY "teams"."id" ASC LIMIT 1 => #<Team id: 1> 2.2.3 :011 > membership = Membership.new(user: user, team: team) => #<Membership id: nil, user_id: 1, team_id: 1> 2.2.3 :012 > membership.save (0.1ms) begin transaction SQL (1.2ms) INSERT INTO "memberships" ("user_id", "team_id") VALUES (?, ?) [["user_id", 1], ["team_id", 1]] (2.3ms) commit transaction => true 记录,并且模型中没有复数错误。将实际MembershipUser个实例传递给TeamMembership.new应该有效。