91

Ben has_and_belongs_to_many ilişkisini gerçekleştirmek istediğim iki model var restaurant ve user.Raylar has_and_belongs_to_many migrasyon

Zaten modeli dosyalarına gitmiş ve has_and_belongs_to_many :restaurants ve has_and_belongs_to_many :users

Ben Raylar 3 ile böyle bir şey yapmak mümkün olmalıdır bu noktada varsayalım ekledik: Ben

rails generate migration .... 

ama her şeyi Denenmiş gibi görünüyor. Eminim ki bu gerçekten basit bir şey. Raylara yeniyim bu yüzden hala öğreniyorum.

cevap

193

Sen alfabetik yılında, sadece bir restaurant_id ve user_id (birincil anahtarı) ile ayrı katılmak tablo eklemek gerekir.

İlk önce geçişlerinizi çalıştırın, ardından oluşturulan geçiş dosyasını düzenleyin.

Raylar 3

rails g migration create_restaurants_users_table 

raylar 4:

rails g migration create_restaurants_users 

Raylarkaynaktan 5

rails g migration CreateJoinTableRestaurantUser restaurants users 

0:

JoinTable adının bir parçası ise tabloları katılmak üretecek bir jeneratör de vardır:


Sizin göç dosyası (:id => false not; o) birincil anahtar oluşturulmasını engeller ne:

Raylar 3

class CreateRestaurantsUsers < ActiveRecord::Migration 
    def self.up 
    create_table :restaurants_users, :id => false do |t| 
     t.references :restaurant 
     t.references :user 
    end 
    add_index :restaurants_users, [:restaurant_id, :user_id] 
    add_index :restaurants_users, :user_id 
    end 

    def self.down 
    drop_table :restaurants_users 
    end 
end 

Raylar

class CreateRestaurantsUsers < ActiveRecord::Migration 
    def change 
    create_table :restaurants_users, id: false do |t| 
     t.belongs_to :restaurant 
     t.belongs_to :user 
    end 
    end 
end 

t.belongs_to 4 otomatik gerekli indeksleri yaratacaktır. def change, bir ileri veya geri alma geçişini otomatik olarak algılar, yukarı/aşağıya gerek yoktur.

Raylar 5

create_join_table :restaurants, :users do |t| 
    t.index [:restaurant_id, :user_id] 
end 

Not: table_name denilen create_join_table parametre olarak geçirilebilir bir özel tablo adı için bir seçenek de vardır.Varsayılan olarak docs

itibaren katılmak tablonun adı alfabetik sırayla, create_join_table sağlanan ilk iki bağımsız değişken birliğinden geliyor. Tablonun adını özelleştirmek için bir sağlayın: TABLE_NAME seçeneği:

+0

Çözüm benim için mükemmel bir şekilde çalıştı. Bu yöntemi kullanırken basit bir hata yaptım, bir komisyonu db denedim: raylar komutundan sonra geçiş yap ve tabloyu oluşturmadı. Bir komisyon db: rollback yapmak zorunda kaldım sonra dosyayı db: d tırma yap ama şimdi her şey çalışıyor. – dbslone

+6

@Dex - Sadece meraktan dolayı, neden ters sütun sırasına göre tanımlanmış ikinci bir bileşik endeks kullandığınızı açıklayabilir misiniz? Sütun düzeninin önemli olmadığı izleniminin altındaydım. Ben DBA değilim, sadece kendi anlayışımı geliştirmek istiyorum. Teşekkürler! – plainjimbo

+9

@Jimbo Bu şekilde buna ihtiyacınız yok, gerçekten sizin sorgularınıza bağlı. Endeksler soldan sağa okunur, böylece 'restaurant_id' üzerinde arama yapıyorsanız ilk mesaj en hızlı olacaktır. İkinci kullanıcı, 'user_id' üzerinde arama yapıyorsanız yardımcı olacaktır. Her ikisinde de arama yapıyorsanız, veritabanının sadece bir tanesine ihtiyaç duyacak kadar akıllı olacağını düşünürdüm. Yani sanırım ikinci olanın bir hayli birleştirilmesi gerekmiyor. Bu sadece bir örnek oldu. Bu bir Rails sorusuydu, bu yüzden DB bölümünde gönderme daha eksiksiz bir yanıt verecekti. – Dex

6

HABTM ilişkileri, bir katılmak tablo oluşturmak gerekir. Sadece birleştirme tablosu vardır ve bu tablonun bir kimlik sütunu olmamalıdır. Bu geçişi deneyin. katılmak tablo oluştururken

def self.up 
    create_table :restaurants_users, :id => false do |t| 
    t.integer :restaurant_id 
    t.integer :user_id 
    end 
end 

def self.down 
    drop_table :restaurants_users 
end 

Sen

+0

'da kullanılabileceğine dikkat etmek istiyorum. Bir modele ihtiyacınız olduğunu düşünmüyorum ve HABTM ilişkisi için bir modele ihtiyaç duyan bağlantıda hiçbir şey göremiyorum. –

+1

Oluşturulan sorguları hızlandırmak için, kimlik alanlarına indeksler ekleyin. –

24

this relationship rails guide tutorials kontrol etmeli iki tablo göç adı/sınıfta alfabetik listelenen gereken şartına dikkat edin. Bu, model adlarınız benzerse sizi kolayca sorabilir. "abc" ve "abb". Çalıştırmak için olsaydı

rails g migration create_abc_abb_table 

Kişisel ilişkiler değil eser beklendiği gibi. Bunun yerine,

rails g migration create_abb_abc_table 

'u kullanmalısınız.

+0

Hangisi önce gelir? foo veya foo_bar? –

+1

@BSeven Ne tür bir unix sıraladığını söylerim. – shacker

+0

Raylar konsolunda bulundu: ["foo_bar", "foo", "foo bar"]. Sort # => ["foo", "foo çubuğu", "foo_bar"] Unix sıralaması aynıdır. – Shadoath

23

Buradaki cevaplar oldukça eskidir. Rails 4.0.2'den itibaren, geçişleriniz create_join_table'dan faydalanmaktadır. İlgili satırları uncomment

class CreateJoinTableRestaurantsUsers < ActiveRecord::Migration 
    def change 
    create_join_table :restaurants, :users do |t| 
     # t.index [:restaurant_id, :user_id] 
     # t.index [:user_id, :restaurant_id] 
    end 
    end 
end 

Eğer bu sütunlar endeksi istiyorsanız ve gitmek için iyi bir konum:

rails g migration CreateJoinTableRestaurantsUsers restaurant user 

Bu şu şekilde görüntülenir:

göçü yaratmak için, koşmak !