gerar modelo usando user: reference vs user_id: integer

176

Estou confuso sobre como gerar um modelo que pertence a outro modelo. Meu livro usa essa sintaxe para associar Micropost ao usuário:

rails generate model Micropost user_id:integer

mas http://guides.rubyonrails.org/ diz para fazê-lo assim:

rails generate model Micropost user:references

As migrações geradas por esses 2 são diferentes. Além disso, para o primeiro, como o Rails sabe que user_idé uma referência de chave estrangeira user? Obrigado!

stackOverlord
fonte

Respostas:

190

Ambos irão gerar as mesmas colunas quando você executar a migração. No console do rails, você pode ver que este é o caso:

:001 > Micropost
=> Micropost(id: integer, user_id: integer, created_at: datetime, updated_at: datetime)

O segundo comando adiciona um belongs_to :userrelacionamento ao seu modelo Micropost, enquanto o primeiro não. Quando esse relacionamento é especificado, o ActiveRecord assume que a chave estrangeira é mantida na user_idcoluna e usará um modelo nomeado Userpara instanciar o usuário específico.

O segundo comando também adiciona um índice na nova user_idcoluna.

Jon M.
fonte
1
É possível gerar um modelo com referências de duas tabelas
praveenkumar
Observe que ele não adiciona uma associação has_many no outro modelo (usuário), que você também pode querer adicionar.
Sv1 27/06/19
45

como os trilhos sabem que user_idé uma referência de chave estrangeira user?

O próprio Rails não sabe que user_idé uma referência de chave estrangeira user. No primeiro comando, rails generate model Micropost user_id:integerele adiciona apenas uma coluna, user_idmas o Rails não conhece o uso do col. Você precisa colocar manualmente a linha no Micropostmodelo

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

as palavras-chave belongs_toe has_manydeterminar a relação entre esses modelos e declarar user_idcomo uma chave estrangeira para o Usermodelo.

O comando posterior rails generate model Micropost user:referencesadiciona a linha belongs_to :userno Micropostmodelo e declara como uma chave estrangeira.

Para sua informação,
declarar as chaves estrangeiras usando o método anterior apenas permite que o Rails saiba sobre o relacionamento que os modelos / tabelas têm. O banco de dados é desconhecido sobre o relacionamento. Portanto, quando você gera os diagramas EER usando um software como MySql Workbencho encontrado, não há segmentos de relacionamento desenhados entre os modelos. Como na foto a seguir insira a descrição da imagem aqui

No entanto, se você usar o método posterior, verá que o arquivo de migração se parece com:

def change
    create_table :microposts do |t|
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :microposts, :users

Agora a chave estrangeira está definida no nível do banco de dados. e você pode gerar EERdiagramas adequados . insira a descrição da imagem aqui

ilusionista
fonte
1
Parece que o último gerador do Rails substituiu a add_foreign_keyação por uma opção foreign_key: truepara a t.referenceslinha, o que implica index: true. Então é agora t.references :user, foreign_key: true. No momento, não há documentação para a foreign_keyopção disponível, portanto essa é apenas minha suposição.
Franklin Yu
Ah, a add_referenceação tem uma :foreign_keyopção que adiciona uma restrição de chave estrangeira apropriada . Eu acho que essa opção faria o mesmo ao criar a tabela.
Franklin Yu
Como você exporta o seu ruby ​​db para o ambiente de trabalho? você poderia talvez responder isso aqui: stackoverflow.com/questions/42982921/…
Krawalla 23/03
Ter add_foreign_key :microposts, :users alguma diferença para o Rails?
Linus
17

Para o primeiro, convenção sobre configuração. O padrão do Rails quando você faz referência a outra tabela com

 belongs_to :something

é procurar something_id.

references, ou belongs_toé realmente a maneira mais nova de escrever o primeiro com algumas peculiaridades.

Importante é lembrar que ele não criará chaves estrangeiras para você. Para fazer isso, você precisa configurá-lo explicitamente usando:

t.references :something, foreign_key: true
t.belongs_to :something_else, foreign_key: true

ou (observe o plural):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Krule
fonte
1
você pode explicar o que você quer dizer com dizer que as referências não criarão chaves estrangeiras para você. Como é diferente do primeiro comando usando user_id: integer diretamente?
22612
Não é, exceto no caso de você estar usando a :polymorphicopção (que IMHO, na maioria dos casos, não é uma boa ideia). Se você deseja utilizar chaves estrangeiras no ActiveRecord, use estrangeiro .
Krule 23/07/12
1
@Krule Now add_foreign_keychegou ao ActiveRecord.
Franklin Yu