5

मुझे किसी भी मॉडल से संबंधित विदेशी कुंजी के रूप में एक मॉडल की उम्मीद नहीं है!सक्रिय रिकॉर्ड has_many विदेशी कुंजी के साथ एसक्यूएल उत्पन्न करता है IS NULL

मेरे पास निम्नलिखित रेल ऐप हैं, चींटियों और चींटी चीजें मॉडलिंग (जोज़ेफ़ द्वारा प्रेरित)।

$ rails -v 
Rails 3.2.8 
$ rails new ant_hill 
$ cd ant_hill 

चींटी पहाड़ी और चींटी मॉडल बनाएं। एक चींटी एक चींटी पहाड़ी से संबंधित हो सकती है और एक चींटी पहाड़ी में कई चींटियां हो सकती हैं।

$ rails generate model AntHill name:string 
$ rails generate model Ant name:string ant_hill_id:integer 
$ vim app/models/ant.rb 
$ cat app/models/ant.rb 
class Ant < ActiveRecord::Base 
    belongs_to :ant_hill 
end 
$ vim app/models/ant_hill.rb 
$ cat app/models/ant_hill.rb 
class AntHill < ActiveRecord::Base 
    has_many :ants 
end 
$ rake db:migrate 
== CreateAntHills: migrating ================================================= 
-- create_table(:ant_hills) 
    -> 0.0013s 
== CreateAntHills: migrated (0.0016s) ======================================== 

== CreateAnts: migrating ===================================================== 
-- create_table(:ants) 
    -> 0.0035s 
== CreateAnts: migrated (0.0037s) ============================================ 

कंसोल में निम्न कोड चलाएं।

$ rails c 
Loading development environment (Rails 3.2.8) 

कुछ चींटियों को बनाए रखें, बने रहें, जो किसी भी चींटी पहाड़ी से संबंधित नहीं हैं।

1.9.2-p290 :001 > Ant.create! name: "August" 
=> #<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06"> 
1.9.2-p290 :002 > Ant.create! name: "Bertil" 
=> #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13"> 

अब एक चींटी पहाड़ी को तुरंत चालू करें, लेकिन इसे अभी तक बचाएं नहीं।

1.9.2-p290 :003 > ant_hill = AntHill.new name: "Storkullen" 
=> #<AntHill id: nil, name: "Storkullen", created_at: nil, updated_at: nil> 

मुझे उम्मीद है कि इस चींटी पहाड़ी में कोई चींटियां नहीं हैं और ऐसा नहीं है।

1.9.2-p290 :004 > ant_hill.ants 
=> [] 

मुझे अभी भी चींटी पहाड़ी की कोई चींटियां नहीं होने की उम्मीद है लेकिन अब इसमें दो हैं।

1.9.2-p290 :005 > ant_hill.ants.count 
    (0.1ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" IS NULL 
=> 2 

वही यहां, विदेशी कुंजी से निपटने के दौरान इसे कभी भी "आईएस न्यूल" युक्त क्वेरी उत्पन्न नहीं करनी चाहिए। मेरा मतलब है "संबंधित_यूएलएल" कुछ भी नहीं हो सकता है, है ना?

1.9.2-p290 :006 > ant_hill.ants.all 
    Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" IS NULL 
=> [#<Ant id: 1, name: "August", ant_hill_id: nil, created_at: "2012-09-27 12:01:06", updated_at: "2012-09-27 12:01:06">, #<Ant id: 2, name: "Bertil", ant_hill_id: nil, created_at: "2012-09-27 12:01:13", updated_at: "2012-09-27 12:01:13">] 

इसे जारी रखने के बाद यह अपेक्षित व्यवहार करता है।

1.9.2-p290 :007 > ant_hill.save! 
=> true 
1.9.2-p290 :008 > ant_hill.ants.count 
    (0.4ms) SELECT COUNT(*) FROM "ants" WHERE "ants"."ant_hill_id" = 1 
=> 0 
1.9.2-p290 :009 > ant_hill.ants.all 
    Ant Load (0.4ms) SELECT "ants".* FROM "ants" WHERE "ants"."ant_hill_id" = 1 
=> [] 

कोई अंतर्दृष्टि? क्या यह अपेक्षित व्यवहार है?

उत्तर

1

हालांकि यह counterintuitive लगता है, मुझे लगता है कि यह व्यवहार आपके उदाहरणों को समझ में आता है। उदाहरण के लिए ant_hill.ants.count लें। गणना एक ActiveRecord क्वेरी विधि है जो डेटाबेस को हिट करती है, और आप अनिवार्य रूप से ActiveRecord से उन सभी चींटियों को देने के लिए कह रहे हैं जो चींटी पहाड़ी से संबंधित नहीं हैं। रेल बस आपको कुछ ऐसा करने की अनुमति दे रही है जो आपको करने में सक्षम नहीं होना चाहिए, और इसके बारे में शिकायत नहीं करना चाहिए। क्या इसे इसके बजाय अपवाद उठाया जाना चाहिए? संभवतः।

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

ant_hill.ants.size 

इस तरह की विषमता के आसपास आप एक तरह से प्राप्त कर सकते हैं, इसकी उपस्थिति को सत्यापित करके ant_hill_id को एक आवश्यक फ़ील्ड बनाना है।

टीएल; डीआर सक्रिय ऑब्जेक्ट क्वेरी इंटरफ़ेस का उपयोग करने से बचें यदि पैरेंट ऑब्जेक्ट डेटाबेस पर नहीं रहता है।

+0

मैं इस मामले में ant_hill_id की आवश्यकता नहीं कर सकता क्योंकि मेरा एप्लिकेशन चींटियों को अनुमति देता है जो किसी भी चींटी पहाड़ी से संबंधित नहीं हैं। – ludde

+0

'.size' का उपयोग करके आपके मामले में काम करना चाहिए – PinnyM

+1

स्पष्ट होने के लिए, मैं पहले से ही अपने ऐप में इस समस्या के आसपास काम कर रहा हूं और मुझे पता है कि इसके आसपास काम करने के कई तरीके हैं। मुझे नहीं लगता कि यह अपेक्षित व्यवहार है।जब कुछ में कोई विदेशी विदेशी कुंजी होती है, तो इसका मतलब है कि यह किसी भी चीज़ से संबंधित नहीं है। मुझे लगता है कि आप तर्क दे सकते हैं कि एक सहेजी गई चींटी पहाड़ी डेटाबेस के परिप्रेक्ष्य से कुछ भी नहीं है, लेकिन वास्तव में नहीं। – ludde

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