Какая разница между принадлежащим и has_one?

Ответы:

241

По сути, они делают то же самое, единственная разница в том, на какой стороне отношений вы находитесь. Если a Userимеет a Profile, то в Userклассе, который у вас есть, has_one :profileи в Profileклассе, который у вас будет belongs_to :user. Чтобы определить, кто «имеет» другой объект, посмотрите, где находится внешний ключ. Мы можем сказать, что User«имеет» a, Profileпотому что в profilesтаблице есть user_idстолбец. Однако если бы profile_idв usersтаблице был вызван столбец , мы бы сказали, что a Profileимеет a User, и местоположения own_to / has_one поменяется местами.

вот более подробное объяснение.

ryeguy
источник
ok имеет смысл, has_a является свойством, а принадлежность - это скорее отношение.
Бланкмен
48
Так сказать, это очень коротко: Product belongs_to Shopозначает, что в productsтаблице есть shop_idстолбец
Йо Людке
@ryeguy, а как насчет того, чтобы это были отношения с самим собой?
Ариан Фауртош
49

Это о том, где находится внешний ключ.

class Foo < AR:Base
end
  • Если foo belongs_to :bar, то в таблице foos есть bar_idстолбец
  • Если foo has_one :bar, то таблица баров имеет foo_idстолбец

На концептуальном уровне, если у вас class Aесть has_oneотношения с, class Bто class 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)
)
Чандан Кумар Маллик
источник
Это в значительной степени совпадает с принятым ответом двухлетней давности.
Матиас Крулл
11
Это в значительной степени лучший ответ.
typeoneerror
Использование Accountи Userв этом примере является неудачным, поскольку часто бывает, что у учетной записи может быть много пользователей.
Кармаказе
5

has_oneи, belongs_toкак правило, одинаковы в том смысле, что они указывают на другую связанную модель. belongs_toубедитесь, что эта модель имеет foreign_keyопределенную has_oneгарантирует, что другой has_foreignключ модели определен.

Чтобы быть более конкретным, есть две стороны relationship, одна из которых Ownerи другая Belongings. Если has_oneопределено только, мы можем получить его, Belongingsно не можем получить Ownerиз belongings. Чтобы отследить, 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

Это добавит метод 'author' в модель Book.
Подробнее о режиме см. Руководства

Сомеш Шарма
источник
0

С точки зрения простоты, belongs_toэто лучше, чем has_oneпотому has_one, что в , вы должны добавить следующие ограничения к модели и таблице, имеющей внешний ключ, для обеспечения has_oneвзаимосвязи:

  • validates :foreign_key, presence: true, uniqueness: true
  • добавить уникальный индекс базы данных по внешнему ключу.
konyak
источник