Qual é a diferença entre belongs_to e has_one?

Respostas:

241

Eles essencialmente fazem a mesma coisa, a única diferença é de que lado do relacionamento você está. Se a Usertiver um Profile, na Userclasse que você teria has_one :profilee na Profileclasse que você teria belongs_to :user. Para determinar quem "possui" o outro objeto, observe onde está a chave estrangeira. Podemos dizer que um User"tem" a Profileporque a profilestabela possui uma user_idcoluna. Se houvesse uma coluna chamada profile_idna userstabela, no entanto, diríamos que a Profilepossui a User, e os locais belongs_to / has_one seriam trocados.

Aqui está uma explicação mais detalhada.

ryeguy
fonte
ok faz sentido, has_a é propriedade, enquanto pertencer é mais uma relação.
Blankman
48
Então quer dizer que realmente curta: Product belongs_to Shopmeios productstabela tem shop_idcoluna
Yo Ludke
@ryeguy, e se esse é um relacionamento de auto-participação?
Arian Faurtosh
49

É sobre onde fica a chave estrangeira.

class Foo < AR:Base
end
  • Se foo belongs_to :bar, a tabela foos tem uma bar_idcoluna
  • Se foo has_one :bar, a tabela de barras tem uma foo_idcoluna

No nível conceitual, se você class Atem um has_onerelacionamento com ele, class Bentão class Aé o pai de, class Bportanto, class Bele terá um belongs_torelacionamento com class Aele, pois é filho de class A.

Ambos expressam um relacionamento 1-1. A diferença é principalmente onde colocar a chave estrangeira, que fica na mesa da classe que declara o belongs_torelacionamento.

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

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

As tabelas para essas classes podem se parecer com:

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)
)
Chandan Kumar Mallik
fonte
Isso é praticamente o mesmo que a resposta aceita de dois anos atrás já declara.
Matthias krull
11
Esta é praticamente uma resposta melhor.
typeoneerror
O uso de Accounte Userneste exemplo é lamentável, pois geralmente é o caso em que uma conta pode ter muitos usuários.
Karmakaze 12/07/19
5

has_onee belongs_togeralmente são iguais no sentido em que apontam para o outro modelo relacionado. belongs_tocertifique-se de que este modelo tenha o foreign_keydefinido. has_onegarante que a outra has_foreignchave de modelo seja definida.

Para ser mais específico, existem dois lados de relationship, um é o Ownere outro é Belongings. Se only has_onefor definido, podemos obtê-lo, Belongingsmas não podemos obtê-lo a Ownerpartir do belongings. Para rastrear o Owner, precisamos definir o belongs_totambém no modelo pertencente.

ilusionista
fonte
3

Outra coisa que quero acrescentar é: suponha que tenhamos a seguinte associação de modelos

class Author < ApplicationRecord has_many :books end

se escrevermos apenas a associação acima, poderemos obter todos os livros de um autor em particular,

@books = @author.books

Mas para um livro em particular, não podemos obter o autor correspondente por,

@author = @book.author

para que o código acima funcione, precisamos adicionar associação ao modelo Book também, como este

class Book < ApplicationRecord
  belongs_to :author
end

Isso adicionará o método 'author' ao modelo do livro.
Para detalhes do modo, consulte os guias

Somesh Sharma
fonte
0

Do ponto de vista da simplicidade, belongs_toé melhor do que has_oneporque has_one, você teria que adicionar as seguintes restrições ao modelo e tabela que possui a chave estrangeira para reforçar o has_onerelacionamento:

  • validates :foreign_key, presence: true, uniqueness: true
  • adicione um índice exclusivo do banco de dados à chave estrangeira.
konyak
fonte