Computer >> कंप्यूटर >  >> प्रोग्रामिंग >> Ruby

अपनी बढ़ती उपयोगकर्ता तालिका को कैसे वश में करें

क्लाइंट वहां कैसे पहुंचा?

विवरण में गोता लगाने से पहले, आइए यह समझने की कोशिश करें कि इस स्थिति में कोई ऐप कैसे समाप्त हो सकता है। हम एक साधारण users . से शुरू करते हैं मेज़। कुछ हफ्तों के बाद, हमें अंतिम साइन इन समय निर्धारित करने में सक्षम होना चाहिए ताकि हम users.last_sign_in_at जोड़ सकें। . फिर हमें यूजर का नाम जानना होगा। हम first_name add जोड़ते हैं और last_name . ट्विटर हैंडल? एक और कॉलम। गिटहब प्रोफाइल? फ़ोन नंबर? कुछ महीनों के बाद तालिका दिमागी दबदबा बन जाती है।

इसमें क्या गलत है?

एक बड़ी तालिका कई समस्याओं को इंगित करती है:

  1. User कई असंबंधित जिम्मेदारियां हैं। इससे इसे समझना, बदलना और परीक्षण करना अधिक कठिन हो जाता है।
  2. ऐप और डेटाबेस के बीच डेटा का आदान-प्रदान करने के लिए अतिरिक्त बैंडविड्थ की आवश्यकता होती है।
  3. भारी मॉडल को स्टोर करने के लिए ऐप को अधिक मेमोरी की आवश्यकता होती है।

ऐप ने User प्राप्त किया प्रमाणीकरण और प्राधिकरण उद्देश्यों के लिए प्रत्येक अनुरोध पर लेकिन आमतौर पर केवल कुछ ही कॉलम का उपयोग किया जाता है। समस्या को ठीक करने से डिज़ाइन और प्रदर्शन दोनों में सुधार होगा।

तालिका निकालना

हम शायद ही कभी इस्तेमाल किए गए कॉलम को नई टेबल (या टेबल) में एक्सट्रेक्ट करके समस्या का समाधान कर सकते हैं . उदाहरण के लिए, हम प्रोफ़ाइल जानकारी निकाल सकते हैं (first_name , आदि) profiles . में निम्नलिखित चरणों के साथ:

  1. profiles users . में प्रोफ़ाइल से संबंधित स्तंभों को डुप्लिकेट करने वाले स्तंभों के साथ ।
  2. profile_idजोड़ें users . के लिए . इसे NULL . पर सेट करें अभी के लिए।
  3. users में प्रत्येक पंक्ति के लिए , profiles . में एक पंक्ति डालें जो प्रोफ़ाइल-संबंधित कॉलम को डुप्लिकेट करता है।
  4. बिंदु profile_id users . में संबंधित पंक्ति का 3 में डाली गई पंक्ति में।
  5. नहीं नहीं users.profile_id make बनाएं गैर-NULL . ऐप को अभी तक अपने अस्तित्व के बारे में पता नहीं है इसलिए यह टूट जाएगा।

हमें संदर्भों को users.first_name . से बदलना होगा profiles.first_name . के साथ और इसी तरह। यदि हम मुट्ठी भर संदर्भों के साथ केवल कुछ कॉलम निकाल रहे हैं तो मेरा सुझाव है कि हम इसे मैन्युअल रूप से करें। लेकिन जैसे ही हम सोचते हैं "ओह, नहीं। यह अब तक का सबसे खराब काम है!" हमें एक विकल्प की तलाश करनी चाहिए।

समस्या की उपेक्षा न करें। कोड का एक हिस्सा जिससे हर कोई बचता है वह और भी खराब हो जाएगा और अधिक असावधानी से पीड़ित होगा . दुष्चक्र को तोड़ने का सबसे आसान तरीका है छोटी शुरुआत करना।

आगे पढ़ें, यदि आप उत्सुक हैं कि मेरे मुवक्किल ने समस्या का समाधान कैसे किया।

कोड को एक बार में एक लाइन ठीक करना

सबसे वृद्धिशील दृष्टिकोण एक समय में पुराने कॉलम के एक संदर्भ को ठीक कर रहा है। आइए first_name को स्थानांतरित करने पर ध्यान दें users . से profiles . के लिए ।

सबसे पहले, Profile create बनाएं साथ:

rails generate model Profile first_name:string

फिर users . से एक संदर्भ जोड़ें profiles . के लिए और कॉपी करें users.first_name profiles . के लिए :

class ExtractUsersFirstNameToProfiles < ActiveRecord::Migration
  # Redefine the models to break dependency on production code. We need
  # vanilla models without callbacks, etc. Also, removing a model in the future
  # might break the migration.
  class User < ActiveRecord::Base; end
  class Profile < ActiveRecord::Base; end
 
  def up
    add_reference :users, :profile, index: true, unique: true, foreign_key: true
 
    User.find_each do |user|
      profile = Profile.create!(first_name: user.first_name)
      user.update!(profile_id: profile.id)
    end
 
    change_column_null :users, :profile_id, false
  end
 
  def down
    remove_reference :users, :profile
  end
end

क्योंकि यह प्रत्येक उपयोगकर्ता को ठीक एक प्रोफ़ाइल के लिए बाध्य करता है, users . से एक संदर्भ profiles . के लिए विपरीत संदर्भ के लिए बेहतर है।

डेटाबेस संरचना के साथ, हम first_name . को प्रत्यायोजित कर सकते हैं User . से Profile . पर . मेरे मुवक्किल की कई आवश्यकताएं थीं:

  1. एक्सेसर्स को संबंधित profiles का उपयोग करना चाहिए . उन्हें यह भी लॉग इन करना चाहिए कि पदावनत एक्सेसर को कहाँ से बुलाया गया था।
  2. User सहेजा जा रहा है Profile automatically को अपने आप सहेजना चाहिए बहिष्कृत एक्सेसर्स का उपयोग करके कोड को तोड़ने से बचने के लिए।
  3. User#first_name_changed? और अन्य ActiveModel::Dirty विधियों को अभी भी काम करना चाहिए।

इसका अर्थ है User इस तरह दिखना चाहिए:

class User < ActiveRecord::Base
  # We need autosave as the client code might be unaware of
  # Profile#first_name and still reference User#first_name.
  belongs_to :profile, autosave: true
 
  def first_name
    log_backtrace(:first_name)
    profile.first_name
  end
 
  def first_name=(new_first_name)
    log_backtrace(:first_name)
 
    # Call super so that User#first_name_changed? and similar still work as
    # expected.
    super
 
    profile.first_name = new_first_name
  end
 
  private
 
  def log_backtrace(name)
    filtered_backtrace = caller.select do |item|
      item.start_with?(Rails.root.to_s)
    end
    Rails.logger.warn(<<-END)
A reference to an obsolete attribute #{name} at:
#{filtered_backtrace.join("\n")}
END
  end
end

इन परिवर्तनों के बाद, ऐप वही काम करता है लेकिन Profile के अतिरिक्त संदर्भों के कारण थोड़ा धीमा हो सकता है (यदि प्रदर्शन एक मुद्दा बन जाता है तो बस ऐपसिग्नल जैसे टूल का उपयोग करें)। कोड विरासती विशेषताओं के सभी संदर्भों को लॉग करता है, यहां तक ​​कि अप्राप्य भी (उदा. user[attr] = ... या user.send("#{attr}=", ...) ) इसलिए हम grep . होने पर भी उन सभी का पता लगा पाएंगे अनुपयोगी है।

इस बुनियादी ढांचे के साथ, हम users.first_name . के एक संदर्भ को ठीक करने के लिए प्रतिबद्ध हो सकते हैं नियमित समय पर, उदा। हर सुबह (जल्दी जीत के साथ दिन की शुरुआत करने के लिए) या दोपहर के आसपास (एक केंद्रित सुबह के बाद कुछ आसान काम करने के लिए)। यह प्रतिबद्धता आवश्यक है क्योंकि हमारा लक्ष्य समस्या को ठीक करने के लिए मानसिक बाधाओं को कम करना है . ऊपर दिए गए कोड को बिना कार्रवाई किए छोड़ देने से ऐप और भी खराब हो जाएगा।

सभी पदावनत संदर्भों को हटाने के बाद (और grep . के साथ पुष्टि करते हुए) और लॉग) हम अंत में users.first_name . को छोड़ सकते हैं :

class RemoveUsersFirstName < ActiveRecord::Migration
  def change
    remove_column :users, :first_name, :string
  end
end

हमें User . में जोड़े गए कोड से भी छुटकारा पाना चाहिए क्योंकि अब इसकी आवश्यकता नहीं है।

सीमाएं

यह विधि आपके मामले पर लागू हो सकती है लेकिन इसकी कुछ सीमाओं को ध्यान में रखें:

  • यह User.update_all जैसी बल्क क्वेरी को हैंडल नहीं करता है ।
  • यह कच्ची SQL क्वेरी को हैंडल नहीं करता है।
  • यह बंदर-पैच तोड़ सकता है (याद रखें कि निर्भरताएं उन्हें भी पेश कर सकती हैं)।
  • User और profiles अगर profiles.first_name . तो सिंक से बाहर हो सकता है अपडेट किया गया है लेकिन users.first_name नहीं है।

आप उनमें से कुछ पर काबू पाने में सक्षम हो सकते हैं। उदाहरण के लिए, आप मॉडल को सर्विस ऑब्जेक्ट के साथ सिंक में रख सकते हैं या profiles . पर कॉलबैक कर सकते हैं . या यदि आप PostgreSQL का उपयोग करते हैं तो आप अंतरिम में एक भौतिक दृश्य का उपयोग करने पर विचार कर सकते हैं।

बस!

लेख का सबसे महत्वपूर्ण सबक यह है कि उस कोड से बचें, जिससे बदबू आती है, लेकिन इसके बजाय इससे निपटें . यदि कार्य भारी है तो नियमित समय पर पुनरावृत्त रूप से कार्य करें। लेख प्रस्तुत किया गया a तालिका निकालने पर विचार करने की विधि कठिन है। यदि आप इसे लागू नहीं कर सकते हैं तो कुछ और देखें। अगर आपको पता नहीं है कि कैसे तो बस मुझे एक लाइन छोड़ दो। मैं मदद करने की कोशिश करूंगा। अपने बिट्स को सड़ने न दें।


  1. अपने पीसी पर MX प्लेयर कैसे स्थापित करें?

    इससे कोई फर्क नहीं पड़ता कि आप एक फिल्म हैं जंकी या एक नियमित एंड्रॉइड उपयोगकर्ता, आपने एमएक्स प्लेयर के बारे में सुना होगा। आप में से जो एमएक्स प्लेयर के बारे में नहीं जानते हैं, उनके लिए यह एक मीडिया प्लेयर है जो आपको हर तरह के ऑडियो और वीडियो मुफ्त में चलाने की सुविधा देता है। एमएक्स प्लेयर आपको

  1. अपने विंडोज 10 पीसी को कैसे गति दें।

    यदि आप अपने विंडोज 10 कंप्यूटर को गति देने के तरीकों की तलाश कर रहे हैं, तो आप सही जगह पर हैं। आज तक मैंने कई विंडोज 10 कंप्यूटर देखे और ठीक किए हैं जो धीमे चल रहे थे, यहां तक ​​कि नए - और माना जाता है कि तेज - पीसी। मेरे अनुभव के अनुसार, सिस्टम के प्रदर्शन को प्रभावित करने वाले कई कारणों से विंडोज

  1. फेसबुक कैसे आपका विश्वास हासिल करने की कोशिश कर रहा है?

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