Migracja Railsów: t.references z alternatywną nazwą?

121

Mam więc tabelę create_table taką jak ta dla kursów w szkole:

create_table :courses do |t|
  t.string :name
  t.references :course
  t.timestamps
end

ale chcę, aby odnosił się do dwóch innych kursów, takich jak:

has_many :transferrable_as # A Course
has_many :same_as          # Another Course

Czy mogę powiedzieć, co następuje?

t.references :transferrable_as, :as=> :course
lustro
źródło

Odpowiedzi:

161

Możesz to wszystko zrobić we wstępnej migracji / definicji kolumny (przynajmniej obecnie w Railsach 5):

t.references :transferable_as, index: true, foreign_key: {to_table: :courses}
t.references :same_as, index: true, foreign_key: {to_table: :courses}
Ryan
źródło
10
Działa to na Railsach 5.1 i żadna inna sugestia nie działa. Jest znacznie czystszy i dobrze się czuje.
stephenmurdoch
2
Używam Railsów 5.1.4, ale to nie działa. Kiedy określam foreign_keyopcję w tworzeniu tabeli w ten sposób, pojawia się błąd mówiący, że sama tabela, którą tworzę, nie istnieje ... Więc podejrzewam, że nie jest obsługiwana przez oficjalne API.
Quv
3
Przeczytałem również, że indexjest już dodany do kluczy obcych od stackoverflow.com/questions/39769981/ ...
Jonathan Reyes
98

Możesz to zrobić w ten sposób:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as
  t.references :same_as
  t.timestamps
end

lub używając t.belongs_to jako aliasu dlat.references

Nie możesz dodać foreign_key: true do tych dwóch linii odniesienia. Jeśli chcesz oznaczyć je jako klucze obce na poziomie bazy danych, musisz przeprowadzić migrację z tym:

add_foreign_key :courses, :courses, column: :transferrable_as_id
add_foreign_key :courses, :courses, column: :same_as_id

Aktualizacja

W Railsach 5.1 i nowszych możesz dodać klucz obcy do migracji w create_tablebloku w następujący sposób:

create_table :courses do |t|
  t.string :name
  t.references :transferrable_as, foreign_key: { to_table: 'courses' }
  t.references :same_as, foreign_key: { to_table: 'courses' }
  t.timestamps
end
Toby 1 Kenobi
źródło
5
Ta część dotycząca niemożności dodania foreign_key: truedo linii referencyjnych była tym, co mnie zaskoczyło. Dodanie add_foreign_keyi określenie nazwy kolumny dla nich załatwiło sprawę.
Matthew Clark,
Czy to działa po wyjęciu z pudełka w Railsach? Według stackoverflow.com/a/22384289/239657 , do tego potrzebny jest schema_plusklejnot. Dokumentacja add_reference w Railsach nie wspomina o opcjach: odwołań.
Beni Cherniavsky-Paskin
1
Nie podążam za tym, do czego references:służy ta opcja (w przeciwieństwie do t.referencesczy nie byłoby to istotne tylko na poziomie modelu, z uwzględnieniem kwestii Foreign_key add_foreign_key?
MCB
1
@MCB t.referencesmówi „dodaj pole do tej tabeli, które jest kluczem podstawowym innej tabeli”. Ta references:opcja mówi, która tabela jest kluczem podstawowym (potrzebne, jeśli nazwa pola nie jest jasna). add_foreign_keyFunkcja informuje bazę do przymusowego integralność referencyjna tutaj.
Toby 1 Kenobi
2
@MCB po tylu latach zdaję sobie sprawę, że miałeś rację. Twój pierwszy komentarz powyżej jest dokładnie poprawny - add_foreign_keylinie dbają o poinformowanie bazy danych, jaki jest klucz obcy do czego. references:Parametr robi nic.
Toby 1 Kenobi
13

Myślę, że ten wątek ma inny, bardziej Railsowy sposób: Scaffolding ActiveRecord: dwie kolumny tego samego typu danych

W migracji:

t.belongs_to: transferrable_as

t.belongs_to: same_as

lustro
źródło
1
ale skąd db wie, z którym kluczem obcym połączyć tabelę? Próbuję tego z bazą danych Postgres i powoduje to błąd, PG::UndefinedTable: ERRORże próbuje dodać ograniczenie klucza obcego do tabeli, która nie istnieje.
Toby 1 Kenobi
W przypadku gdy ktoś zastanawia się, belongs_toto tylko aliasem do referencesi tak ma dokładnie taką samą funkcjonalność.
Jason Swett
11

Jako dodatkowa odpowiedź na to pytanie - Model powinien mieć następującą linię, aby uzupełnić skojarzenie:

    belongs_to :transferrable_as, class_name: "Course"
    belongs_to :same_as, class_name: "Course"
Diego Diaz de Berenguer
źródło
3

Myślę, że nie referencesakceptuje tej :asopcji, ale możesz ręcznie utworzyć kolumny ...

create_table :courses do |t| 
  t.string  :name 
  t.integer :course1_id
  t.integer :course2_id 
  t.timestamps 
end 
Ju Nogueira
źródło