मान्य करने के लिए प्रतीत होता है मुझे एक ऐसी स्थिति मिली है जहां ActiveRecord बाल रिकॉर्ड को अनावश्यक रूप से मान्य कर रहा है। लंबाई के लिए अग्रिम में क्षमा करें क्योंकि यह काफी जटिल है।ActiveRecord अपरिवर्तित बाल रिकॉर्ड को अनावश्यक रूप से
इसमें उन संगठनों के माध्यम से शामिल है जिनका पहले उपयोग किया गया था लेकिन किसी भी तरह से नहीं बदला गया था। यह 3.2 से हाल के मास्टर तक होता है। मुझे यकीन नहीं है कि यह एक डिज़ाइन निर्णय है जिसने अप्रत्याशित व्यवहार या किसी प्रकार की बग का नेतृत्व किया है।
मैं वास्तविक कोड से एक टेस्ट केस को कम कर दिया इस प्रकार है:
मॉडल:
class A < ActiveRecord::Base
belongs_to :b
has_many :cs, :through => :b
before_validation { puts "A" }
end
class B < ActiveRecord::Base
has_many :as
has_many :cs
before_validation { puts "B" }
end
class C < ActiveRecord::Base
belongs_to :b
before_validation { puts "C" }
end
प्रवासन:
class AddABC < ActiveRecord::Migration
def change
create_table :as do |t|
t.references :b
end
create_table :bs do |t|
end
create_table :cs do |t|
t.references :b
end
end
end
कम परीक्षण का मामला है कि चलाता है यह इस जब रन है एक खाली डेटाबेस पर:
b = B.create!
c = C.create!
b.cs << c
a = A.new
a.b = b
a.cs.first
puts "X"
a.valid?
जो उत्पादन देता है:
B
C
C
X
A
C
कौन सा पता चलता है कि एक एक मान्य अपनी सी सत्यापित करता है।
अब इसे ध्यान में रखते हुए मुझे has_many :validate => false
विकल्प से अवगत है, और इसका उपयोग करके, समस्या दूर हो जाती है। लेकिन ऐसा लगता है कि यहां से और अधिक चल रहा है - मेरे साथ भालू।
: मान्य जब जनक वस्तु बचत यदि गलत, इनसे संबंधित वस्तुओं को मान्य नहीं है। डिफ़ॉल्ट रूप से सच है।
लेकिन मुझे लगता है स्पष्ट रूप से इस रूप में इस भ्रामक सभी रिकॉर्ड का मतलब यह नहीं कर सकते हैं। यदि मैं कभी भी एसोसिएशन नहीं प्राप्त करता हूं (उपरोक्त कोड से a.cs.first
हटाएं), तो मुझे ऑब्जेक्ट्स मान्य नहीं होंगे, या मुझे यह मिल जाएगा लेकिन इसका कभी भी उपयोग नहीं करें (a.cs
के साथ प्रतिस्थापित करें)।
def validate_collection_association(reflection)
if association = association_instance_get(reflection.name)
if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave])
records.each_with_index { |record, index| association_valid?(reflection, record, index) }
end
end
end
यह association_instance_get
जो संघ कैश से हासिल करेगा पर सभी सशर्त है: यह इसलिए है क्योंकि यह lib/active_record/autosave_association.rb
जो कोड भी शामिल है में validate_collection_association
माध्यम से चला जाता है। कोई कैश का मतलब मान्य करने के लिए कोई रिकॉर्ड नहीं है।
मैंने केवल एक बी मॉडल स्थापित करके एक सरल है Imany करने की कोशिश की है, जो ए को संदर्भित करता है, लेकिन फिर मुझे ए से पहले बी बनाने की आवश्यकता होगी, फिर अगर मैं कोशिश करता हूं तो ए एक नया रिकॉर्ड नहीं होगा इसे सहेजने के लिए, और इस कोड समस्या से बचाता है के रूप में शाखा कहा जाता है अब पहले हो जाएगा:
def associated_records_to_validate_or_save(association, new_record, autosave)
if new_record
association && association.target
elsif autosave
association.target.find_all(&:changed_for_autosave?)
else
association.target.find_all(&:new_record?)
end
end
केवल वास्तविक विवरण मैं इसे केवल भरी हुई रिकॉर्ड सत्यापित करने के साथ आ सकता है क्योंकि ActiveRecord के इरादे यहाँ केवल बदले गए रिकॉर्ड मान्य करने के लिए है। असल में मैं उम्मीद करता हूं कि यह सत्यापित करने के लिए और केवल तभी सहेजा जा रहा है, और इसलिए बदले गए रिकॉर्ड्स को सहेजने के डिफ़ॉल्ट ऑटोसेव विकल्प को सत्यापन को रोकना चाहिए।
मुझे related ticket और 27aa4dda7d89ce733 प्रतिबद्ध है (अभी तक मुझे लगता है कि किसी भी रिलीज में नहीं) जो एक बदलाव करता है लेकिन मेरे परीक्षण से इस विशिष्ट मुद्दे को ठीक नहीं करता है।हालांकि यह अभिव्यक्ति को नियंत्रित करता है:
!record.persisted? || record.changed? || record.marked_for_destruction?
और अगर मैं validate_collection_association
के अंतरतम पाश को यह शर्त जोड़ तो समस्या ActiveRecord परीक्षण अभी भी मेरे मशीन पर गुजर के साथ, चला जाता है।
यह मेरी परियोजना में एक महत्वपूर्ण प्रदर्शन मुद्दा रहा है क्योंकि प्रश्न में मॉडल केवल व्यवस्थापक में मान्य होना चाहिए, जहां एक वैध सत्यापन में उपयोग किए गए एक अनदेखा क्षेत्र को सहेजने की दुर्लभता के कारण स्वीकार्य था और इस प्रकार मैं यह तय किया गया कि यह अनुक्रमणित करना अधिक अनुक्रमणित होगा (यह केवल एक फ़ील्ड नहीं होगा)। जाहिर है ज्यादातर मामलों में यह अति-सत्यापन बहुत कम गंभीर होगा, और यह केवल एक विशिष्ट मामले में होता है, इसलिए यह एक बग हो सकता है।
इसलिए, मुझे यह पता चल गया कि क्या हो रहा है, मुझे पूरा यकीन नहीं है कि क्या हो रहा है, इसलिए मैंने इसे ActiveRecord टिकट के रूप में दायर नहीं किया है। क्या आपको लगता है कि यह एक बग है? यह इस तरह क्यों काम कर रहा है? वास्तव में वैध विकल्प क्या है? यदि यह एक बग है, तो क्या आप समझा सकते हैं कि कोड इस तरह क्यों काम करता है, और यह क्यों अधिक है? ब्रेक के ऊपर ActiveRecord में मेरा कोड किस मामले में बदल जाएगा?
मुझे यह देखने में दिलचस्पी होगी कि क्या इनवर्क्स_ओफ़ जोड़ना है: एसोसिएशन पर इस व्यवहार को बिल्कुल बदल दिया गया है। टीबीएच मुझे कोई बड़ी उम्मीद नहीं है कि यह होगा, हालांकि। –
मेरे परीक्षण में यह नहीं था। –