जब ActiveRecord को किसी तालिका के बारे में जानने की आवश्यकता होती है तो यह आपके information_schema
जैसी क्वेरी करता है क्वेरी लेकिन एआर पोस्टग्रेएसक्यूएल-विशिष्ट सिस्टम टेबल
इसके बजाय:
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
FROM pg_attribute a LEFT JOIN pg_attrdef d
ON a.attrelid = d.adrelid AND a.attnum = d.adnum
WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
AND a.attnum > 0 AND NOT a.attisdropped
ORDER BY a.attnum
PostgreSQL अडैप्टर स्रोत खोजें "regclass" के लिए और आप कुछ अन्य प्रश्न देखेंगे जिनका उपयोग AR तालिका की संरचना का पता लगाने के लिए करेगा।
pg_get_expr
कोड>
उपरोक्त क्वेरी में कॉल वह जगह है जहां से कॉलम का डिफ़ॉल्ट मान आता है।
उस क्वेरी के परिणाम, कमोबेश, सीधे PostgreSQLColumn.new
में
:
def columns(table_name, name = nil)
# Limit, precision, and scale are all handled by the superclass.
column_definitions(table_name).collect do |column_name, type, default, notnull|
PostgreSQLColumn.new(column_name, default, type, notnull == 'f')
end
end
PostgreSQLColumn
कंस्ट्रक्टर
extract_value_from_default
रूबी के लिए- डिफ़ॉल्ट रूप से ify; का अंत switch
में extract_value_from_default
यहाँ दिलचस्प है:
else
# Anything else is blank, some user type, or some function
# and we can't know the value of that, so return nil.
nil
इसलिए यदि डिफ़ॉल्ट मान एक अनुक्रम के लिए बाध्य है (जो एक id
. है पोस्टग्रेएसक्यूएल में कॉलम होगा), फिर डिफ़ॉल्ट डेटाबेस से इस तरह के फ़ंक्शन कॉल के रूप में बाहर आ जाएगा:
nextval('models_id_seq'::regclass)
वह ऊपर else
में समाप्त होगा शाखा और column.default.nil?
सच होगा।
id
. के लिए कॉलम यह कोई समस्या नहीं है, एआर डेटाबेस से id
. के लिए मूल्यों की आपूर्ति की अपेक्षा करता है कॉलम इसलिए यह परवाह नहीं करता कि डिफ़ॉल्ट मान क्या है।
यह एक बड़ी समस्या है यदि कॉलम का डिफ़ॉल्ट कुछ ऐसा है जिसे AR समझ नहीं पाता है, ऐसे फ़ंक्शन कॉल कहें md5(random()::text)
. के रूप में
. समस्या यह है कि एआर सभी विशेषताओं को उनके डिफ़ॉल्ट मानों के लिए प्रारंभ करेगा - जैसे कि Model.columns
उन्हें देखता है, जैसा कि डेटाबेस उन्हें देखता है - जब आप कहते हैं Model.new
. उदाहरण के लिए, कंसोल में आप इस तरह की चीज़ें देखेंगे:
> Model.new
=> #<Model id: nil, def_is_function: nil, def_is_zero: 0>
तो अगर def_is_function
वास्तव में फ़ंक्शन कॉल को इसके डिफ़ॉल्ट मान के रूप में उपयोग करता है, एआर इसे अनदेखा कर देगा और उस कॉलम के मान के रूप में एक न्यूल डालने का प्रयास करेगा। वह NULL डिफ़ॉल्ट मान का उपयोग होने से रोकेगा और आप एक भ्रमित करने वाली गड़बड़ी के साथ समाप्त हो जाएंगे। डिफ़ॉल्ट जिन्हें एआर समझ सकता है (जैसे स्ट्रिंग्स और नंबर) हालांकि ठीक काम करते हैं।
नतीजा यह है कि आप वास्तव में ActiveRecord के साथ गैर-तुच्छ डिफ़ॉल्ट कॉलम मानों का उपयोग नहीं कर सकते हैं, यदि आप एक गैर-तुच्छ मान चाहते हैं तो आपको रूबी में ActiveRecord कॉलबैक में से एक के माध्यम से करना होगा (जैसे before_create
)।
आईएमओ यह बहुत बेहतर होगा यदि एआर ने डिफ़ॉल्ट मानों को डेटाबेस तक छोड़ दिया अगर यह उन्हें समझ में नहीं आया:उन्हें INSERT से बाहर छोड़कर या VALUES में DEFAULT का उपयोग करने से बेहतर परिणाम मिलेंगे; एआर, निश्चित रूप से, सभी उचित डिफ़ॉल्ट प्राप्त करने के लिए डेटाबेस से नई बनाई गई वस्तुओं को फिर से लोड करना होगा, लेकिन अगर एआर को समझ में नहीं आया तो आपको केवल फिर से लोड करने की आवश्यकता होगी। अगर else
में extract_value_from_default
nil
. के बजाय एक विशेष "मैं नहीं जानता इसका क्या अर्थ है" ध्वज का उपयोग किया तो "मुझे पहली बार सहेजने के बाद इस ऑब्जेक्ट को फिर से लोड करने की आवश्यकता है" स्थिति का पता लगाने के लिए तुच्छ होगा और आप केवल आवश्यक होने पर ही पुनः लोड करेंगे।
उपरोक्त PostgreSQL-विशिष्ट है लेकिन प्रक्रिया अन्य डेटाबेस के लिए समान होनी चाहिए; हालांकि, मैं कोई गारंटी नहीं देता।