wygeneruj model przy użyciu user: referencje vs user_id: integer

176

Nie wiem, jak wygenerować model, który należy do innego modelu. Moja książka używa tej składni do powiązania Micropost z użytkownikiem:

rails generate model Micropost user_id:integer

ale http://guides.rubyonrails.org/ mówi, żeby zrobić to w ten sposób:

rails generate model Micropost user:references

Migracje generowane przez te 2 są różne. Ponadto, w przypadku pierwszego, skąd railsy wiedzą, że user_idjest to odwołanie do klucza obcego user? Dzięki!

stackOverlord
źródło

Odpowiedzi:

190

Obie wygenerują te same kolumny po uruchomieniu migracji. W konsoli railsów widać, że tak jest:

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

Drugie polecenie dodaje belongs_to :userrelację w modelu Micropost, podczas gdy pierwsze nie. Gdy ta relacja jest określona, ​​ActiveRecord przyjmie, że klucz obcy jest przechowywany w user_idkolumnie i użyje modelu o nazwie Userdo utworzenia wystąpienia określonego użytkownika.

Drugie polecenie dodaje również indeks do nowej user_idkolumny.

Jon M.
źródło
1
Czy można wygenerować model z odniesieniami do dwóch tabel
praveenkumar
Zauważ, że nie dodaje asocjacji has_many do innego modelu (użytkownika), którą możesz również chcieć dodać.
Sv1
45

skąd railsy wiedzą, że user_idodwołuje się do klucza obcego user?

Same Railsy nie wiedzą, że user_idjest to odwołanie do klucza obcego user. W pierwszym poleceniu rails generate model Micropost user_id:integerdodaje tylko kolumnę, user_idale rails nie znają użycia col. Musisz ręcznie umieścić linię w Micropostmodelu

class Micropost < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :microposts
end

słowa kluczowe belongs_toi has_manyokreśl związek między tymi modelami i zadeklaruj user_idjako klucz obcy do Usermodelu.

Późniejsze polecenie rails generate model Micropost user:referencesdodaje linię belongs_to :userdo Micropostmodelu i niniejszym deklaruje jako klucz obcy.

FYI
Zadeklarowanie kluczy obcych przy użyciu poprzedniej metody pozwala jedynie Railsom wiedzieć o relacji między modelami / tabelami. Baza danych nie jest znana na temat relacji. Dlatego podczas generowania diagramów EER przy użyciu oprogramowania takiego jak MySql Workbenchokazuje się, że między modelami nie ma wątków relacji. Jak na poniższym zdjęciu wprowadź opis obrazu tutaj

Jeśli jednak użyjesz późniejszej metody, okaże się, że plik migracji wygląda następująco:

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

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

Teraz klucz obcy jest ustawiony na poziomie bazy danych. i możesz wygenerować odpowiednie EERdiagramy. wprowadź opis obrazu tutaj

iluzjonista
źródło
1
Wydaje się, że generator ostatnie Szyny zastąpił add_foreign_keydziałania z opcją foreign_key: truedo t.referenceslinii, co oznacza index: true. Tak jest teraz t.references :user, foreign_key: true. Obecnie nie ma dokumentacji dotyczącej tej foreign_keyopcji, więc jest to tylko moje założenie.
Franklin Yu
Aha, add_referenceakcja ma :foreign_keyopcję, która dodaje odpowiednie ograniczenie klucza obcego . Myślę, że ta opcja zrobiłaby to samo podczas tworzenia tabeli.
Franklin Yu
Jak wyeksportować Ruby DB do Środowiska pracy? czy mógłbyś odpowiedzieć na to tutaj: stackoverflow.com/questions/42982921/…
Krawalla
Czy ma add_foreign_key :microposts, :users to jakieś znaczenie dla Railsów?
Linus,
17

W pierwszym przypadku konwencja nad konfiguracją. Railsy są domyślne, gdy odwołujesz się do innej tabeli z

 belongs_to :something

jest szukać something_id.

references, a belongs_towłaściwie jest nowszym sposobem pisania tego pierwszego z kilkoma dziwactwami.

Należy pamiętać, że nie utworzy on dla Ciebie kluczy obcych. Aby to zrobić, musisz ustawić to jawnie za pomocą:

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

lub (zwróć uwagę na liczbę mnogą):

add_foreign_key :table_name, :somethings
add_foreign_key :table_name, :something_elses`
Krule
źródło
1
czy możesz wyjaśnić, co masz na myśli, mówiąc, że odwołania nie utworzą dla ciebie kluczy obcych. Czym różni się od pierwszego polecenia używającego bezpośrednio user_id: integer?
shailesh
Tak nie jest, z wyjątkiem przypadku, gdy używasz :polymorphicopcji (która IMHO w większości przypadków nie jest dobrym pomysłem). Jeśli chcesz używać kluczy obcych w ActiveRecord, użyj obcego .
Krule,
1
@Krule Teraz add_foreign_keytrafił do ActiveRecord.
Franklin Yu