रेलों के पास_और_बेलॉग_टो_मनी माइग्रेशन है


119

मेरे दो मॉडल हैं restaurantऔर userमैं एक has_and_belongs_to_many संबंध करना चाहता हूं।

मैं पहले से ही मॉडल फ़ाइलों में चले गए और जोड़ लिया है has_and_belongs_to_many :restaurantsऔरhas_and_belongs_to_many :users

मुझे लगता है कि इस बिंदु पर मुझे कुछ ऐसा करने में सक्षम होना चाहिए जैसे रेल 3:

rails generate migration ....

लेकिन मैंने जो भी कोशिश की है वह सब विफल होता दिख रहा है। मुझे यकीन है कि यह वास्तव में सरल है मैं रेल के लिए नया हूं इसलिए मैं अभी भी सीख रहा हूं।

जवाबों:


260

आप एक अलग ही एक साथ तालिका में शामिल होने के जोड़ने की जरूरत है restaurant_idऔर user_id(कोई प्राथमिक कुंजी), में वर्णमाला के क्रम

पहले अपना माइग्रेशन चलाएं, फिर जनरेट हुई माइग्रेशन फ़ाइल को संपादित करें।

रेल 3

rails g migration create_restaurants_users_table

रेल 4 :

rails g migration create_restaurants_users

रेलें ५

rails g migration CreateJoinTableRestaurantUser restaurants users

से डॉक्स :

एक जनरेटर भी है जो JoinTable नाम का हिस्सा होने पर तालिकाओं का उत्पादन करेगा:


आपकी माइग्रेशन फ़ाइल (नोट :id => false; यह वही है जो प्राथमिक कुंजी के निर्माण को रोकती है):

रेल 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

रेलें ४

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स्वचालित रूप से आवश्यक सूचकांकों का निर्माण करेगा। def changeऑटो आगे या रोलबैक माइग्रेशन का पता लगाएगा, ऊपर / नीचे की कोई आवश्यकता नहीं है।

रेलें ५

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

नोट: कस्टम तालिका नाम के लिए एक विकल्प भी है जिसे create_join_table नामक पैरामीटर के रूप में पारित किया जा सकता है table_name। से डॉक्स

डिफ़ॉल्ट रूप से, शामिल होने की तालिका का नाम वर्णानुक्रम क्रम में create_join_table को प्रदान किए गए पहले दो तर्कों के संघ से आता है। तालिका का नाम अनुकूलित करने के लिए, एक: table_name विकल्प प्रदान करें:


8
@Dex - जिज्ञासा से बाहर, क्या आप बता सकते हैं कि आप एक दूसरे कंपाउंड इंडेक्स का उपयोग क्यों कर रहे हैं, जिसे उल्टे कॉलम ऑर्डर के साथ परिभाषित किया गया है? मैं इस धारणा के तहत था कि कॉलम ऑर्डर से कोई फर्क नहीं पड़ता। मैं कोई डीबीए नहीं हूं, बस अपनी समझ को आगे बढ़ाना चाहता हूं। धन्यवाद!
सादेजिमो

11
@ जिम्बो आपको इसकी आवश्यकता नहीं है, यह वास्तव में आपके प्रश्नों पर निर्भर करता है। अनुक्रमित बाएं से दाएं पढ़ा जाता है, इसलिए यदि आप खोज कर रहे हैं तो पहला सबसे तेज़ होगा restaurant_id। यदि आप खोज कर रहे हैं तो दूसरा मदद करेगा user_id। यदि आप दोनों को खोज रहे हैं, तो मुझे लगता है कि डेटाबेस केवल एक की आवश्यकता के लिए पर्याप्त स्मार्ट होगा। इसलिए मुझे लगता है कि दूसरे को वास्तव में मिश्रित होने की आवश्यकता नहीं है। यह सिर्फ एक उदाहरण से अधिक था। हालांकि यह एक रेल सवाल था, इसलिए डीबी अनुभाग में पोस्ट करने से अधिक पूर्ण उत्तर मिलेगा।
डेक्स

3
दूसरे इंडेक्स में कुछ अतिरेक है - जब तक आप दोनों रेस्तरां_आईडी और यूजर_आईडी पर क्वेरी कर रहे हैं, आपके एसक्यूएल में उनका क्रम मायने नहीं रखता है, और पहले इंडेक्स का उपयोग किया जाएगा। यह भी इस्तेमाल किया जाएगा यदि आप केवल restaurant_id पर क्वेरी कर रहे हैं। दूसरा इंडेक्स केवल उसी पर होना चाहिए: user_id, और उन मामलों में उपयोग किया जाएगा जहां आप केवल user_id पर क्वेरी कर रहे हैं (जो कि पहले इंडेक्स इसकी कुंजियों के क्रम के कारण मदद नहीं करेगा)।
यार्डबॉय

13
रेल में 4 माइग्रेशन अंत में टेबल केrails g migration create_restaurants_users बिना होना चाहिए ।
Fa11enAngel

6
तुम भी रेल जी प्रवास CreateJoinTableRestaurantUser रेस्तरां उपयोगकर्ता का उपयोग कर सकते हैं। पढ़ें गाइड .rubyonrails.org
migrations.html

36

यहाँ के उत्तर काफी दिनांकित हैं। रेल 4.0.2 के रूप में, आपके माइग्रेशन का उपयोग करते हैं create_join_table

माइग्रेशन बनाने के लिए, रन करें:

rails g migration CreateJoinTableRestaurantsUsers restaurant user

यह निम्नलिखित उत्पन्न करेगा:

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

यदि आप इन स्तंभों को अनुक्रमित करना चाहते हैं, तो संबंधित पंक्तियों को अनसुना करें और आप जाने के लिए अच्छे हैं!


2
मैं आम तौर पर सूचकांक लाइनों में से एक को अनसुना कर देता हूं और unique: trueइसे जोड़ देता हूं । इससे नकली रिश्तों को बनने से रोका जा सकेगा।
टॉबी 1 केनोबी

26

ज्वाइन टेबल बनाते समय, इस आवश्यकता पर विशेष ध्यान दें कि माइग्रेशन नाम / कक्षा में दो तालिकाओं को वर्णमाला क्रम में सूचीबद्ध करने की आवश्यकता है । यह आसानी से आपको काट सकता है यदि आपके मॉडल के नाम समान हैं, उदाहरण के लिए "एबीसी" और "एबीबी"। अगर तुम दौड़ना था

rails g migration create_abc_abb_table

आपके संबंध अपेक्षा के अनुरूप काम नहीं करेंगे। तुम्हें अवश्य उपयोग करना चाहिए

rails g migration create_abb_abc_table

बजाय।


1
जो पहले आता है? foo या foo_bar?
बी सेवन

1
एक रेल कंसोल में रैन: ["foo_bar", "foo", "foo bar"]। सॉर्ट # => ["foo", "foo bar", "foo_bar"] Unix सॉर्ट उसी पर आता है।
शामदो

6

HABTM संबंधों के लिए, आपको एक जॉइन टेबल बनाने की जरूरत है। केवल जॉइन टेबल है और उस टेबल में एक आईडी कॉलम नहीं होना चाहिए। इस माइग्रेशन को आज़माएं।

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

आपको इस रिलेशनशिप गाइड गाइड ट्यूटोरियल की जांच करनी चाहिए


मुझे नहीं लगता कि आपको एक मॉडल की आवश्यकता है और मुझे HABTM संबंध के लिए एक मॉडल की आवश्यकता के बारे में लिंक में कुछ भी दिखाई नहीं देता है।
बी सेवन

1
उत्पन्न प्रश्नों को गति देने के लिए, आईडी फ़ील्ड में सूचक जोड़ें।
मार्टिन रोबर्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.