7

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

class AddColorToGroup < ActiveRecord::Migration 
    def self.up 
    add_column :groups, :color, :string 
    Groups = Group.all.each do |g| 
     c = "red" if g.is_active && is_live 
     c = "green" if g.is_active 
     c = "orange" 
     g.update_attribute(:type, c) 
    end 
    end 

    def self.down 

    end 
end 
+0

डाउन रिवर्स कुछ ऐसा क्यों करता है जो ऊपर नहीं हुआ? – Robert

+0

यह सिर्फ एक टाइपो है जिसे मैंने यहां संपादित करते समय बनाया है;) – user1404536

उत्तर

1

मैं अपने ActiveRecord मॉडल में एक

after_create 
# or 
after_save 

में यह करना होगा:

या प्रवास में आप शायद इस तरह की कुछ एसक्यूएल कर दिया था:

execute('update groups set color = <another column>') 

यहां एक उदाहरण है गाइड रेल:

http://guides.rubyonrails.org/migrations.html#using-the-up-down-methods

+2

धन्यवाद, लेकिन कॉलम सभी मौजूदा समूहों के लिए पूर्व-जनसंख्या होना चाहिए। यह केवल नए बनाए गए समूहों के लिए काम करेगा। – user1404536

2

मैं अत्यधिक तीन कुल खोजों के बजाय का सुझाव देते हैं जाएगा। एक सरणी में वस्तुओं के एक समूह पर हमेशा डेटाबेस बनाम लूपिंग का लाभ उठाएं। मुझे लगता है कि ऐसा कुछ काम कर सकता है।

इसे लिखने के प्रयोजनों के लिए, मुझे लगता है कि is_active जांच एक फ़ील्ड सक्रिय है जहां 1 सक्रिय है। मुझे लगता है कि लाइव भी वही है।

रेल 3 दृष्टिकोण

class AddColorToGroup < ActiveRecord::Migration 
    def self.up 
    add_column :groups, :color, :string 
    Group.where(active: 1, live: 1).update_all(type: "red") 
    Group.where(active: 1, live: 0).update_all(type: "green") 
    Group.where(active: 0, live: 0).update_all(type: "orange") 
    end 
end 

update_all here के दस्तावेज़ की समीक्षा के लिए स्वतंत्र महसूस।

रेल 2.x दृष्टिकोण

class AddColorToGroup < ActiveRecord::Migration 
    def self.up 
    add_column :groups, :color, :string 
    Group.update_all("type = red", "active = 1 AND live = 1") 
    Group.update_all("type = red", "active = 1 AND live = 0") 
    Group.update_all("type = red", "active = 0 AND live = 0") 
    end 
end 

Rails 2 documentation

+0

:(मेरा आवेदन रेल का उपयोग नहीं कर रहा है 3. धन्यवाद हालांकि! – user1404536

+0

उत्तर के रेल 2.x संस्करण को शामिल करने के लिए अद्यतन किया गया है। – Robert

+0

क्या यह आपकी समस्या का समाधान करता है? – Robert

12

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

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

मेरा पसंदीदा समाधान सादे एसक्यूएल का उपयोग करके इस तरह के सभी माइग्रेशन करना है। ऐसा लगता है कि आप पहले ही इसे मान चुके हैं, इसलिए मुझे लगता है कि आप पहले ही जानते हैं कि वहां क्या करना है।

एक अन्य विकल्प है, अगर आप कुछ बालों व्यापार तर्क है या आप केवल अधिक Railsy देखने के लिए कोड चाहते हैं, के रूप में यह मौजूद माइग्रेशन माइग्रेशन फ़ाइल अपने आप में लिखा है मॉडल के मूल संस्करण शामिल करने के लिए है।आपके मामले में

class Group < ActiveRecord::Base 
end 

, कि अकेले शायद गारंटी नहीं है कि मॉडल को तोड़ने नहीं होगा पर्याप्त है: उदाहरण के लिए, आप माइग्रेशन फ़ाइल में इस वर्ग डाल सकता है। मान लें कि active और live इस समय तालिका में बूलियन फ़ील्ड हैं (और इस तरह जब भी यह माइग्रेशन भविष्य में चलाया जाएगा), आपको किसी और कोड की आवश्यकता नहीं होगी। यदि आपके पास अधिक जटिल व्यावसायिक तर्क था, तो आप इसे मॉडल के इस माइग्रेशन-विशिष्ट संस्करण में शामिल कर सकते हैं।

आप अपने मॉडल से माइग्रेशन संस्करण में पूरी विधियों की प्रतिलिपि बनाने पर भी विचार कर सकते हैं। यदि आप ऐसा करते हैं, तो ध्यान रखें कि आपको अपने ऐप में किसी भी बाहरी मॉडल या पुस्तकालयों का संदर्भ नहीं देना चाहिए, या तो अगर भविष्य में वे कोई मौका बदल जाएंगे। इसमें रत्न शामिल हैं और यहां तक ​​कि संभवतः कुछ मूल रूबी/रेल वर्ग भी हैं, क्योंकि रत्नों में एपीआई-ब्रेकिंग परिवर्तन बहुत आम हैं (मैं आपको देख रहा हूं, रेल 3.0, 3.1, और 3.2!)।

0

इसी तरह की स्थिति में मैंने add_column का उपयोग करके कॉलम जोड़ना शुरू किया और फिर कॉलम के मान को अपडेट करने के लिए प्रत्यक्ष SQL का उपयोग कर समाप्त किया। मैंने प्रत्यक्ष एसक्यूएल का इस्तेमाल किया और मॉडल Jim Stewart's answer पर मॉडल नहीं किया, तब से यह मॉडल की वर्तमान स्थिति पर निर्भर करता है, जो तालिका के मौजूदा राज्य को चलने वाले माइग्रेशन के आधार पर निर्भर करता है।

class AddColorToGroup < ActiveRecord::Migration 
    def up 
    add_column :groups, :color, :string 
    execute "update groups set color = case when is_active and is_live then 'red' when is_active then 'green' else 'orange' end" 
    end 

    def down 
    remove_column :groups, :color 
    end 
end 
संबंधित मुद्दे