Emirates_to和has_one有什么区别?


Answers:


241

他们本质上是做相同的事情,唯一的区别是您在关系的哪一边。如果a User有一个Profile,则在User班级has_one :profileProfile班级都有belongs_to :user。要确定谁“拥有”另一个对象,请查看外键在哪里。我们可以说User“有” a是Profile因为profiles表中有一user_id列。但是,如果profile_idusers表上有一列被调用,我们可以说a Profile具有一个User,并且bewhens_to / has_one位置将被交换。

是更详细的说明。


好的,has_a是属性,而属则更多是关系。
Blankman

47
所以说这真的很短:Product belongs_to Shop手段products表有shop_id
哟Ludke

@ryeguy,如果这是自我加入关系,该怎么办?
阿里安(Arian Faurtosh)

49

关于外键的位置。

class Foo < AR:Base
end
  • 如果为foo belongs_to :bar,则foos表中有一bar_id
  • 如果为foo has_one :bar,则bars表中有一foo_id

从概念上讲,如果您class Ahas_one关联,class Bclass A是的父级,class B因此您class B将与belongs_to关联,class A因为它是的子级class A

两者都表示1-1关系。区别主要是在哪里放置外键,该键在声明belongs_to关系的类的表上。

class User < ActiveRecord::Base
  # I reference an account.
  belongs_to :account
end

class Account < ActiveRecord::Base
  # One user references me.
  has_one :user
end

这些类的表可能类似于:

CREATE TABLE users (
  id int(11) NOT NULL auto_increment,
  account_id int(11) default NULL,
  name varchar default NULL,
  PRIMARY KEY  (id)
)

CREATE TABLE accounts (
  id int(11) NOT NULL auto_increment,
  name varchar default NULL,
  PRIMARY KEY  (id)
)

这与两年前已经接受的答案几乎相同。
matthias krull 2012年

11
这是一个更好的答案。
typeoneerror

指某东西的用途 AccountUser在此示例中和是很不幸的,因为一个帐户通常可以有许多用户。
karmakaze

5

has_onebelongs_to一般都是在一定意义上同它们指向其他相关模型。belongs_to确保该模型已foreign_key定义。 has_one确保has_foreign定义了另一个模型密钥。

更具体地说,有的两个方面relationship,一个是Owner,另一个是Belongings。如果只has_one定义,我们可以得到它Belongings,但无法获得Ownerbelongings。为了追踪,Owner我们需要belongs_to在所属模型中定义。


3

我要添加的另一件事是,假设我们具有以下模型关联

class Author < ApplicationRecord has_many :books end

如果我们只写上述关联,那么我们可以通过以下方式获得特定作者的所有书籍:

@books = @author.books

但是对于一本书,我们无法找到相应的作者,

@author = @book.author

为了使上述代码正常工作,我们还需要向Book模型添加关联,就像这样

class Book < ApplicationRecord
  belongs_to :author
end

这会将方法“作者”添加到Book模型中。
有关模式的详细信息,请参见指南


0

从简单性的角度来看,belongs_to它比has_onein中更好,因为 has_one您必须向具有外键以执行has_one关系的模型和表添加以下约束:

  • validates :foreign_key, presence: true, uniqueness: true
  • 在外键上添加数据库唯一索引。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.