2013-04-23 7 views
9

हमारे पास दो मॉडल के बीच एक सरल has_and_belongs_to_many संबंध है। हम उस मॉडल में कुछ पैरामीटर में जोड़ना चाहते हैं, इसलिए हमें इसे मॉडल_शैनी के माध्यम से बदलना होगा: मॉडल के प्रकार के माध्यम से।has_and_belongs_to_many के पास has_many के माध्यम से माइग्रेट कैसे करें?

जैसा कि मुझे पता है, हमें एक आईडी कॉलम में जोड़ना होगा (साथ ही जो भी कॉलम हम अतिरिक्त रूप से चाहते हैं)। हालांकि, मैं यह कैसे करना है इस पर 100% स्पष्ट नहीं हूं। यदि हम एक पूर्णांक कॉलम जोड़ते हैं: आईडी, रेलगाड़ियों को पता चलेगा कि वह 'आईडी' प्राथमिक कुंजी है?

हम नवीनतम 3.x का उपयोग कर रहे हैं।

उत्तर

7

बस अपनी मेज पर आईडी जोड़ने के प्रवास में: has_and_belong_to कई रेल द्वारा बनाई गई के लिए अपने डेटाबेस तालिका मान लिया जाये कि

add_column :table, :id, :primary_key

से this answer

+0

यह उत्पादन में पहले से चल रहे किसी एप्लिकेशन के लिए सबसे अच्छा समाधान नहीं हो सकता है, खासकर जब उपयोगकर्ता नियमित आधार पर तालिका से रिकॉर्ड्स अपडेट/डालने/हटा सकते हैं। – Todd

6

यहां एक पोस्ट है जो एसटीएल का उपयोग habtm तालिका को पैच करने और आईडी (एक पाकी के रूप में) जोड़ने के लिए दिखाती है: Rails modeling: converting HABTM to has_many :through। मुझे उस दृष्टिकोण में परेशानी थी, और डीबी-विशिष्ट मुद्दे हो सकते हैं। मैं जुड़ने (habtm) तालिका को कचरा और एक नया जुड़ने मॉडल बनाने समाप्त हो गया। वह काम किया।

कुछ चेतावनी: ऐसा करने से पहले, मैं गिट में एक शाखा बनाने और डीबी को एक आसान वसूली के लिए संग्रहीत करने की सलाह देता हूं यदि यह किनारे पर जाता है।

  1. संपादित दो में शामिल हो गए मॉडल के मरीजों के लिए एक ही माध्यम से

    class Physician < ActiveRecord::Base 
        # has_and_belongs_to_many :patients 
        has_many :appointments 
        has_many :patients, :through => :appointments 
    end 
    

    has_many उपयोग करने के लिए कार्य करें:

    ये कदम थे।

  2. नए शामिल होने के मॉडल बनाएं:

    rails g model Appointment physician_id:integer patient_id:integer has_insurance:boolean 
    

    संपादित नया माइग्रेशन ऊपर जेनरेट फ़ाइल ... ध्यान दें कि माइग्रेशन विधि के रूप में 'बदलें' काम नहीं करता है, क्योंकि हम डेटा कार्रवाई कर रहे हैं। निचे देखो।

  3. नई DB में मॉडल में शामिल होने और रिकॉर्ड के माध्यम से नए has_many करने के लिए सभी पुराने habtm संघों नक्शा बनाने:

    def self.up 
        create_table :appointments do |t| 
        t.integer :physician_id 
        t.integer :patient_id 
        t.boolean :has_insurance 
    
        t.timestamps 
        end 
    
        Physician.find_each {|doc| 
        doc.patients.each do |pat| 
         Appointment.create!(:physician_id => doc.id, :patient_id => pat.id, :has_insurance => false) 
        end 
        } 
    
        # finally, dump the old hatbm associations 
        drop_table :patients_physicians 
    
    end 
    
  4. यह पुरानी habtm संघों फिर से संगठित करने के लिए एक दर्द का बहुत ज्यादा लगता है, के रूप में रेल गाइड के अनुसार, बस निरस्त करें। नोट, हालांकि, कोई भी इस दृष्टिकोण के साथ माइग्रेशन रोलबैक नहीं कर सकता है।

    def self.down 
        raise ActiveRecord::IrreversibleMigration 
    end 
    

    इसके बजाय, 'नीचे' जाने के लिए, बस गिट शाखा को मार दें, और अपने बैकअप डीबी को पुनः लोड करें। फिर आप डीबी फिर से शुरू कर सकते हैं: यदि आवश्यक हो तो वहां से रोलबैक। आईडी स्तंभ, और डाटाबेस का नाम बदलने:

    def self.down 
        remove_column :appointments, :id 
        rename_table :appointments, :patients_physicians 
    end 
    

    मैं उत्तरार्द्ध का परीक्षण नहीं किया है (मेरे मामले में के रूप में मैं कर दूसरी ओर, अगर रिकॉर्ड के माध्यम से has_many कोई संशोधन की जरूरत है, एक और दृष्टिकोण बस छोड़ने के लिए है मेटाडेटा के साथ गड़बड़ करना है)। ये विचार इस पोस्ट से आए: http://7fff.com/2007/10/31/activerecord-migrating-habtm-to-model-table-suitable-for-has_many-through/

+0

धन्यवाद मोंटी, तुम मुझे बचाने के लिए। बहुत बहुत धन्यवाद – Zakaria

11

संदर्भित patients_physicians

सभी है आपको ऐसा करना होगा जैसे

rails g model patients_physician --skip-migration

तो आप जोड़ सकते हैं जो कुछ भी आप की जरूरत स्तंभ अपने माइग्रेशन की तरह कमांड के साथ

rails g migration add_new_column_to_patients_physician new_column 

करते हैं और अपने डेटा अभी तक सुरक्षित हो जाएगा और आप अपनी क्वेरी आधारित टन मॉडल आप कर सकते हैं उत्पन्न।

न नए जोड़े मॉडल patients_physician

को

belongs_to :model_1 
belongs_to :model_2 

जोड़ने के लिए तो आप मॉडल की जरूरत में करने के लिए उपयोग होगा भूल जाते हैं।

has_many patients_physician 
has_many :model_2, through: :patients_physician 
+0

बहुत अच्छा जवाब। बस आवेदन करने के लिए और कोई साइड इफेक्ट्स के साथ। 'Habtm' एसोसिएशन द्वारा दिए गए सभी पिछले कार्यों को अभी भी उपलब्ध होगा। (जैसे '<< 'या' clear') टिप्पणी का एकमात्र बिंदु नए मॉडल का नाम है जिसे * लिखा जाना चाहिए * जैसा कि आपने लिखा था:' रोगी_फिसशियन 'एकवचन, बहुवचन नहीं। –

4

इस प्रवास मैं टीमें और उपयोगकर्ता के बीच एक has_and_belongs_to_many संबंध परिवर्तित करने के लिए प्रयोग किया जाता है:

class CreateTeamMembers < ActiveRecord::Migration 
    def up 
    # Create a new table with id and timestamps to replace the old one 
    create_table :team_members do |t| 
     t.belongs_to :team 
     t.belongs_to :user 
     t.timestamps 
    end 

    # Now populate it with a SQL one-liner! 
    execute "insert into team_members(team_id,user_id) select team_id,user_id from teams_users" 

    # drop the old table 
    drop_table :teams_users 
    end 

    def down 
    # This leaves the id and timestamps fields intact 
    rename_table :team_members, :teams_users 
    end 
end 
+0

यह एक अच्छा जवाब है क्योंकि यह वापस रोलिंग करते समय डेटा रख रहा है! –

संबंधित मुद्दे