2010-05-22 6 views
6

कुछ बार मैं ऐसी स्थिति में रहा हूं जहां मैं कुछ मॉडल के डिजाइन को दोबारा बनाना चाहता हूं और माइग्रेशन में अद्यतन तर्क डालना समाप्त कर दिया है। हालांकि, जहां तक ​​मैंने समझा है, यह अच्छा अभ्यास नहीं है (विशेष रूप से जब से आपको तैनाती के लिए अपनी स्कीमा फ़ाइल का उपयोग करने के लिए प्रोत्साहित किया जाता है, न कि आपके माइग्रेशन)। आप इस तरह की समस्याओं से कैसे निपटते हैं?अपने माइग्रेशन में अद्यतन तर्क डालना

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

हालांकि, मुझे लगता है कि मुझे कुछ तीसरे प्रकार के उपयोगकर्ता की आवश्यकता है, शायद एक मॉडरेटर या कुछ इसी तरह की। इस मामले में मैं उपयोगकर्ता तालिका से "व्यवस्थापक" ध्वज को हटाने के लिए एक उपयोगकर्ता टाइप मॉडल (और संबंधित माइग्रेशन) जोड़ता हूं, और दूसरा माइग्रेशन जोड़ता हूं। और यहां समस्या आती है। "Add_user_type_to_users" माइग्रेशन में मुझे व्यवस्थापक ध्वज मान को उपयोगकर्ता प्रकार में मैप करना होगा। इसके अतिरिक्त, ऐसा करने के लिए, उपयोगकर्ता प्रकारों का अस्तित्व होना चाहिए, जिसका अर्थ है कि मैं बीज फ़ाइल का उपयोग नहीं कर सकता, बल्कि माइग्रेशन में उपयोगकर्ता प्रकार (खराब अभ्यास भी माना जाता है) बना सकता हूं। यहाँ कुछ काल्पनिक कोड स्थिति का प्रतिनिधित्व करने आता है:

class CreateUserTypes < ActiveRecord::Migration 
    def self.up 
     create_table :user_types do |t| 
      t.string :name, :nil => false, :unique => true 
     end 

     #Create basic types (can not put in seed, because of future migration dependency) 
     UserType.create!(:name => "BASIC") 
     UserType.create!(:name => "MODERATOR") 
     UserType.create!(:name => "ADMINISTRATOR") 
    end 

    def self.down 
     drop_table :user_types 
    end 
end 

class AddTypeIdToUsers < ActiveRecord::Migration 
    def self.up 
     add_column :users, :type_id, :integer 

     #Determine type via the admin flag 
     basic = UserType.find_by_name("BASIC") 
     admin = UserType.find_by_name("ADMINISTRATOR") 
     User.all.each {|u| u.update_attribute(:type_id, (u.admin?) ? admin.id : basic.id)} 

     #Remove the admin flag 
     remove_column :users, :admin 

     #Add foreign key 
     execute "alter table users add constraint fk_user_type_id 
      foreign key (type_id) references user_types (id)" 
    end 

    def self.down 
     #Re-add the admin flag 
     add_column :users, :admin, :boolean, :default => false 

     #Reset the admin flag (this is the problematic update code) 
     admin = UserType.find_by_name("ADMINISTRATOR") 

     execute "update users set admin=true where type_id=#{admin.id}" 

     #Remove foreign key constraint 
     execute "alter table users drop foreign key fk_user_type_id" 

     #Drop the type_id column 
     remove_column :users, :type_id 
    end 
end 

तुम वहाँ दो समस्याग्रस्त हिस्से हैं देख सकते हैं। पहले मॉडल में पंक्ति निर्माण का पहला भाग, जो आवश्यक है यदि मैं एक पंक्ति में सभी माइग्रेशन को चलाने के लिए, फिर "माइग्रेशन" भाग को दूसरे माइग्रेशन में "व्यवस्थापक" कॉलम को "type_id" कॉलम पर मैप करना चाहता हूं।

कोई सलाह?

उत्तर

1

मुझे यह अधिक 'अपरंपरागत' लगता है कि आप fks का उपयोग करते हैं, जिसे आप पुराने उपयोगकर्ता.एडमिन के साथ उपयोगकर्ता टाइप टाइप करते हैं, जो मुझे लगता है कि अक्सर होता है।

यदि आप एफके का उपयोग करते हैं तो आपको बदसूरत mysql त्रुटियां मिलती हैं जो उपयोगकर्ता को भ्रमित करती हैं। यदि अन्यथा आप रेफरेंसियल अखंडता को लागू करने के लिए एआर सत्यापन और हुक का उपयोग करते हैं तो आपको सुंदर और अच्छी तरह से एकीकृत त्रुटि संदेश मिलते हैं जो आपके ऐप के उपयोगकर्ता अनुभव प्रवाह को नहीं तोड़ते हैं।

एक माइग्रेशन के लिए चिंता न करें जो एक बार चलाएगा और आपके तर्क के बाहर जो व्यावसायिक तर्क डाल रहा है उसके बारे में सोचें।

यह राय/सम्मेलन का विषय है, लेकिन मुझे आशा है कि आपको मेरी अंतर्दृष्टि कुछ उपयोगी मिलेगी।

+0

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

+1

मुझे लगता है, यह पसंद का मामला है। यदि बैकअप से परे डेटा अखंडता यूएक्स से अधिक है, तो एफके जाने का रास्ता है। उस स्थिति में आपके पास माइग्रेशन से एफके के प्रबंधन के लिए एक प्लगइन है: http://agilewebdevelopment.com/plugins/foreign_key_migrations – Oinak

+0

ठीक है। टिप के लिए धन्यवाद! –

0

फ़ाइल db/seeds.rb आमतौर पर इस उद्देश्य के लिए प्रयोग किया जाता है - वहाँ में रखा रिकॉर्ड rake db:setup

हालांकि के हिस्से के रूप लोड किया जाएगा, मैं हमेशा पाया है रेल इस समस्या पर नीचे गिर जाता है। मैं एक प्लगइन लिखने के बारे में सोच रहा हूं जो आपको एक डीबी/बीज फ़ोल्डर देता है, रिकॉर्ड (.yml, शायद) जोड़ने के लिए बीजफाइल को डेटस्टैम्प किया गया है और सिस्टम तालिका में बीज डेटा ट्रैक करता है ताकि इसे वापस/अपडेट किया जा सके।

+1

जैसा कि आप कोड में देख सकते हैं, मैं बीज का उपयोग नहीं कर सकता क्योंकि मैं कई बार माइग्रेशन लागू करना चाहता हूं, और अंतिम माइग्रेशन इस बात पर निर्भर करता है कि डेटाबेस में डेटा है। यह अच्छा होगा अगर आप प्रति माइग्रेशन में एक बीज फ़ाइल प्राप्त कर सकें, और बीज फ़ाइलों को माइग्रेशन के बीच लागू किया जाएगा। तो पहले 20100524 ... do_something.rb चलाया जाता है और फिर 20100524 ... seed_something.rb इस माइग्रेशन के लिए आवश्यक बीजिंग करता है। –

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