2012-10-23 13 views
6

सेटअप

इस सवाल के लिए, मैं निम्नलिखित तीन वर्गों का उपयोग करेंगे:रेल 3 के साथ विलय स्कोप मिलती

class SolarSystem < ActiveRecord::Base 
    has_many :planets 

    scope :has_earthlike_planet, joins(:planets).merge(Planet.like_earth) 
end 

class Planet < ActiveRecord::Base 
    belongs_to :solar_system 
    belongs_to :planet_type 

    scope :like_earth, joins(:planet_type).where(:planet_types => {:life => true, :gravity => 9.8}) 
end 

class PlanetType < ActiveRecord::Base 
    has_many :planets 

    attr_accessible :gravity, :life 
end 

समस्या

गुंजाइश has_earthlike_planet काम नहीं करता।

ActiveRecord::ConfigurationError: Association named 'planet_type' was not found; perhaps you misspelled it?

प्रश्न

मुझे पता चला है कि यह है, क्योंकि यह निम्नलिखित के बराबर है: यह मुझे निम्नलिखित त्रुटि देता है

joins(:planets, :planet_type)... 

और SolarSystem एक planet_type संघ नहीं है। मैं Planet पर has_earthlike_planetSolarSystem पर का उपयोग करना चाहता हूं, और कोड और शर्तों को डुप्लिकेट करना से बचाना चाहता हूं। क्या इन स्कॉप्स को मर्ज करने का कोई तरीका है जैसे मैं करने का प्रयास कर रहा हूं लेकिन मुझे एक टुकड़ा याद आ रहा है? यदि नहीं, तो इन लक्ष्यों को पूरा करने के लिए मैं अन्य तकनीकों का उपयोग कैसे कर सकता हूं?

उत्तर

8

जाहिर है, इस समय आप केवल सरल संरचनाओं को मर्ज कर सकते हैं जिनमें शामिल नहीं होते हैं। उम्मीद है कि जल्द ही तय किया जाएगा ...

-

class SolarSystem < ActiveRecord::Base 
    has_many :planets 
    has_many :planet_types, :through => :planets 

    scope :has_earthlike_planet, joins(:planet_types).merge(PlanetType.like_earth) 
end 

class Planet < ActiveRecord::Base 
    belongs_to :solar_system 
    belongs_to :planet_type 

    scope :like_earth, joins(:planet_type).merge(PlanetType.like_earth) 
end 

class PlanetType < ActiveRecord::Base 
    has_many :planets 

    attr_accessible :gravity, :life 

    scope :like_earth, where(:life => true, :gravity => 9.8) 
end 

** अद्यतन **

रिकॉर्ड के लिए, इस व्यवहार के बारे में bug was filed: यहाँ एक संभावित समाधान, अगर आप इस तरह देखने के लिए अपने मॉडल को संशोधित है

+0

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

1

आप Planet.like_earth के दायरे से शर्तों का पुन: उपयोग कर रहे हैं, जो planet_type में शामिल हो जाते हैं। जब इन शर्तों को विलय कर दिया जाता है, planet_type एसोसिएशन को SolarSystem पर बुलाया जा रहा है, जो अस्तित्व में नहीं है।

SolarSystem में planet_typesplanets के माध्यम से planets है, लेकिन यह अभी भी सही एसोसिएशन नाम नहीं है, क्योंकि यह बहुवचन है। planet_type एसोसिएशन को सेट करने के लिए आप SolarSystem कक्षा में निम्नलिखित जोड़ सकते हैं, जो planet_types के लिए केवल एक उपनाम है। हालांकि बाद AREL संघ मैक्रो को दर्शाता है, और मॉडल उस नाम से एक विधि का जवाब है कि क्या पर क्वेरी नहीं करता आप रूबी alias का उपयोग नहीं कर सकते हैं:

class SolarSystem < ActiveRecord::Base 
    has_many :planets 
    has_many :planet_types, :through => :planets 
    has_many :planet_type, :through => :planets, :class_name => 'PlanetType' 

    scope :has_earthlike_planet, joins(:planets).merge(Planet.like_earth) 
end 

SolarSystem.has_earthlike_planet.to_sql # => SELECT "solar_systems".* FROM "solar_systems" INNER JOIN "planets" ON "planets"."solar_system_id" = "solar_systems"."id" INNER JOIN "planets" "planet_types_solar_systems_join" ON "solar_systems"."id" = "planet_types_solar_systems_join"."solar_system_id" INNER JOIN "planet_types" ON "planet_types"."id" = "planet_types_solar_systems_join"."planet_type_id" WHERE "planet_types"."life" = 't' AND "planet_types"."gravity" = 9.8 
+2

सौभाग्य से, टैटूइन के नागरिकों के लिए "एंटरप्राइज़" जैसी कोई चीज़ नहीं है। मुझे लगता है कि आप साम्राज्य का मतलब है। दूसरा, टैटूइन पर कोई मसाला नहीं है - यह सब केसल पर है। अंत में, मुझे लगता है कि आपका मतलब "ग्रह" था, न कि "पौधे"। : पी –

+0

ऐसा लगता है कि यह 'planet_types_solar_systems_join' नामक एक अतिरिक्त अस्थायी संबंध बनाता है। यदि मैं दायरे को 'स्कोप' में बदलता हूं: has_earthlike_planet, जुड़ता है (: planet_type) .merge (Planet.like_earth) '(' ग्रहों की बजाय 'planet_type' पर शामिल होने पर ध्यान दें) क्वेरी सही दिखती है। मुझे पता है कि दृश्यों के पीछे यह 'सौरसिस्टम.जेंक्स (: planet_type,: planet_type) कर रहा है' लेकिन चूंकि इसका कोई दुष्प्रभाव नहीं है, मुझे लगता है कि मैं इसके साथ ठीक हूं। यह निश्चित रूप से एक हैक की तरह लगता है हालांकि रेलों के आसपास घूमने के लिए संशोधित संघों का उपयोग करके शामिल नहीं किया जाता है। – Aaron

0

एक आसान समाधान है कि मैंने पाया कि आप है मिलती है के लिए जो सही तालिका नामों में शामिल हैं हमेशा और इसलिए हमेशा कोई बात नहीं काम करना चाहिए अगर आप गुंजाइश सीधे कॉल या उसका उपयोग

joins(Planet.joins(:planet_type).join_sql) 

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

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