新手问题 傻瓜是这么理解 has_one 与 belongs_to 的 primary_key, foreign_key

breeze · 2016年09月30日 · 最后由 Cauchyzhou 回复于 2017年06月22日 · 4008 次阅读

有人一直弄不清楚,has_one 与 belongs_to 的 primary_key 与 foreign_key 要如何设置。于是我就这么解释了!!!

首先讲 raIls 默认的规则:
class User < ApplicationRecord
  # 当user是主人时, dog是主人的附属品时,应这样设置
  has_one :dog
  has_one :dog, primary_key: :id, foreign_key: :user_id
  # 当我们没有定义任何的primary_key与 foreign_key时
  # rails会默认拿user的主键id 与 dog的外键user_id进行关联,即 primary_key: :id, foreign_key: :user_id
  # 为什么是拿dog的user_id进行关联,因为rails默认外键的规则是: 表名_主键
  # 所以以上两种定义是等价的
end

class Dog < ApplicationRecord

  # 以下两种定义也是等价的
  belongs_to :user
  belongs_to :user, primary_key: :id, foreign_key: :user_id 

  # 这时候,新人就会有疑问了,怎么两个model中的primary_key与foreign_key是一样的
  # 为什么不是默认设置成:
  belongs_to :user, primary_key: :id, foreign_key: :dog_id
end

因为规则是:谁是主人,primary_key 就是默认主人的主键,foreign_key 就是默认附属品的外键,所以不管是 has_one 还是 belongs_to 他们的主人都是 user。

当默认的 foreign_key 不存在时
class User < ApplicationRecord
=begin     表结构
+-----------+----------------------+------+-----+---------+----------------+
| Field     | Type                 | Null | Key | Default | Extra          |
+-----------+----------------------+------+-----+---------+----------------+
| id        | int(11) unsigned     | NO   | PRI | NULL    | auto_increment |
| name      | varchar(21)          | NO   | UNI |         |                |
+-----------+----------------------+------+-----+---------+----------------+
=end

  has_one :dog
  # 当遇到dog这张表中没有 user_id时
  # 如果使用以上关联,则会报错,因为dog表中没有rails默认外键 user_id

  # 此时,如果要成功建立关联,则需要手动指定外键
  # 当dog表中的外键字段是master_id,则需要这样设置:
  has_one :dog, foreign_key: :master_id

end

class Dog < ApplicationRecord
=begin    表结构
+-----------+----------------------+------+-----+---------+----------------+
| Field     | Type                 | Null | Key | Default | Extra          |
+-----------+----------------------+------+-----+---------+----------------+
| id        | int(11) unsigned     | NO   | PRI | NULL    | auto_increment |
| master_id | int(11) unsigned     | NO   | UNI |         |                |
+-----------+----------------------+------+-----+---------+----------------+
=end

  #同样的也需要指明foreign_key,否则通过默认规则会报错
  belongs_to :user, foreign_key: :master_id
end

如果我是新人,你这么说我一样不理解 如果我是你,我会这样说:在这个例子里,外键就是狗牌,你给狗戴的牌子上写的是你自己的姓名地址,而不是狗的名字,这样别人才能通过狗找到你。

我觉得你应该着重指出,has_one 和 belongs_to 后面的 foreign_id 含义是不一样的,一个是「去对面的表里找这个字段」,另一个是「使用这个字段做」

这种东西,你让他自己 new 两个新 model 试一下,比你说一百句都管用 他们自己本来就已经搅不清楚了,又不愿意动手,你给他解释再多也不过换来他们一句:哦,这样啊

#2 楼 @IChou 我觉得说说还是有用的

说的很明白 我觉得说的很好啊

关系数据库的基础知识懂了,这个设置就不难了吧

后面写错了吧

😬 好新的新人

8 楼 已删除

新人表示看懂了,豁然开朗

需要 登录 后方可回复, 如果你还没有账号请 注册新账号