Migrações do Rails 3: Adicionando coluna de referência?

162

Se eu criar uma nova migração do Rails 3 com (por exemplo)

rails g migration tester title:tester user:references

, tudo funciona bem ... no entanto, se eu adicionar uma coluna com algo ao longo das linhas de:

rails g migration add_user_to_tester user:references

o campo de referência não é reconhecido. Em resumo, a pergunta é: como adiciono uma coluna de referência a uma migração de trilhos a partir da linha de comando?

Plâncton
fonte

Respostas:

205

Se você estiver usando o Rails 4.x, agora poderá gerar migrações com referências, desta forma:

rails generate migration AddUserRefToProducts user:references

como você pode ver nos guias de trilhos

Paulo Fidalgo
fonte
1
Veja a seção 2.1 em edgeguides.rubyonrails.org/active_record_migrations.html, por exemplo.
B Seven
2
como você especifica um nome de coluna para a chave estrangeira em vez do nome gerado automaticamente?
j
@jwill você pode usar polymorphic: user: reference {polymorphic}.
Paulo Fidalgo
@PauloFidalgo Você pode explicar um pouco sobre como fazer isso? pode ser algum guia de links? (falando sobre polimórfica)
Anwar
@Anwar: aqui estão os documentos api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/…
Paulo Fidalgo
186

EDIT : Esta é uma resposta desatualizada e não deve ser aplicada ao Rails 4.x +

Você não precisa adicionar referências quando pode usar um ID inteiro para sua classe referenciada.

Eu diria que a vantagem de usar referências em vez de um número inteiro simples é que o modelo será predefinido com perten_to e, como o modelo já foi criado e não será afetado quando você migrar algo existente, o objetivo é meio que perdido.

Então, eu faria assim:

rails g migration add_user_id_to_tester user_id:integer

E, em seguida, adicione manualmente o usuário belongs_to: no modelo do Testador

DanneManne
fonte
9
Mas isso não criará as restrições de chave estrangeira apropriadas nos bancos de dados que suportam, certo?
Abahgat
19
Não, o afaik Rails nunca cria restrições de chave estrangeira no banco de dados, a menos que você adicione plugins para fazer isso por você.
DanneManne
apenas estudar este post, pls como faço para adicionar a referência depois de tudo
El nino
13
lembre-se de adicionar o índice com o usuário: integer: índice
rickypai
3
A resposta está datada, veja a resposta de @ Paulo para trilhos modernos.
OneHoopyFrood
102

Observe que você provavelmente também precisará de um índice nessa coluna.

class AddUserReferenceToTester < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
    add_index  :testers, :user_id
  end
end
Eugene
fonte
1
Por quê? Isso é verdade para a maioria dos relacionamentos de pertences?
ahnbizcad
É de fato por razões de desempenho e é útil se você tiver um has_many / has_one do outro lado dessa relação pertence. Se você tiver certeza absoluta de que não será user.testersaprovado, poderá omitir o índice.
Eugene
1
O rails g migration ...gerado add_reference :installs, :device, index: trueque também cria o índice.
B Seven
49

Com as duas etapas anteriores mencionadas acima, você ainda está perdendo a restrição de chave estrangeira. Isso deve funcionar:

  class AddUserReferenceToTester < ActiveRecord::Migration
      def change
          add_column :testers, :user_id, :integer, references: :users
      end
  end
Martin Cabrera Diaubalick
fonte
Esta é a única resposta real aqui. A chave estrangeira é a parte mais crítica aqui
user2490003 11/11/2015
isto deve ser marcado como a resposta correta, já que as perguntas pede rails 3
Carlos Roque
35

Você pode usar referências em uma migração de alterações. Este é um código válido do Rails 3.2.13:

class AddUserToTester < ActiveRecord::Migration
  def change
    change_table :testers do |t|
      t.references :user, index: true 
    end
  end
  def down
    change_table :testers do |t|
      t.remove :user_id
    end
  end
end

cf: http://apidock.com/rails/ActiveRecord/ConnectionAdapters/SchemaStatements/change_table

gl03
fonte
1
métodos de alteração e redução? não são métodos para cima e para baixo?
MaicolBen
@MaicolBen sim, e você também pode simplesmente deixar de fora o método down.
Hut8
@MaicolBen Sem o downmétodo, recebi ActiveRecord::IrreversibleMigrationao reverter usando o Rails 3.2. Eu também tive que mudar changepara up.
Andrew Grimm
27

A execução rails g migration AddUserRefToSponsors user:referencesgerará a seguinte migração:

def change
  add_reference :sponsors, :user, index: true
end
Wirwing
fonte
Qual é a versão do Rails?
Andrew Grimm
8

Ao adicionar uma coluna, você precisa torná-la um número inteiro e, se possível, manter as convenções de trilhos. Portanto, no seu caso, suponho que você já tenha modelos de Testador e Usuário e tabelas de testadores e usuários.

Para adicionar a chave estrangeira, você precisa criar uma coluna inteira com o nome user_id (convenção):

add_column :tester, :user_id, :integer

Em seguida, inclua um belongs_to no modelo do testador:

class Tester < ActiveRecord::Base
  belongs_to :user
end

E você também pode querer adicionar um índice para a chave estrangeira (isso é algo que as referências já fazem para você):

add_index :tester, :user_id
Zamith
fonte
8

Isso será o suficiente:

rails g migration add_user_to_tester user_id:integer:index
masterweily
fonte
Eu gosto que isso também adicione o índice que você provavelmente desejará.
precisa saber é
3

Você pode adicionar referências ao seu modelo através da linha de comando da seguinte maneira:

rails g migration add_column_to_tester user_id:integer

Isso irá gerar um arquivo de migração como:

class AddColumnToTesters < ActiveRecord::Migration
  def change
    add_column :testers, :user_id, :integer
  end
end

Isso funciona bem toda vez que eu usá-lo ..

Neha
fonte
3

Para Rails 4

O gerador aceita o tipo de coluna como referência (também disponível como belongs_to).

Essa migração criará uma user_idcoluna e um índice apropriado:

$ rails g migration AddUserRefToProducts user:references 

gera:

class AddUserRefToProducts < ActiveRecord::Migration
  def change
    add_reference :products, :user, index: true
  end
end

http://guides.rubyonrails.org/active_record_migrations.html#creating-a-standalone-migration

Para Rails 3

O auxiliar é chamado de referências (também disponível como belongs_to).

Essa migração criará uma category_idcoluna do tipo apropriado. Observe que você passa o nome do modelo, não o nome da coluna. Active Record adiciona o _idpara você.

change_table :products do |t|
  t.references :category
end

Se você tiver belongs_toassociações polimórficas , as referências incluirão as duas colunas necessárias:

change_table :products do |t|
  t.references :attachment, :polymorphic => {:default => 'Photo'}
end

Adicionará uma coluna attachment_id e uma attachment_typecoluna de string com um valor padrão de Photo.

http://guides.rubyonrails.org/v3.2.21/migrations.html#creating-a-standalone-migration

shilovk
fonte