2012-04-27 20 views
6

मेरे पास मेरे रेल एप्लिकेशन में एक स्थिति है जहां मुझे वर्तमान रनटाइम स्थिति के आधार पर मनमाने ढंग से मॉड्यूल शामिल करने की आवश्यकता है। मॉड्यूल कस्टम एप्लिकेशन कोड प्रदान करता है जिसे केवल तभी जरूरी होता है जब कुछ स्थितियां सत्य हों। असल में, मैं वर्तमान संदर्भ से एक कंपनी के नाम पर खींच रहा हूँ और का उपयोग कर कि मॉड्यूल के लिए फ़ाइल नाम और अपनी परिभाषा के रूप में:रूबी: एक गतिशील मॉड्यूल नाम शामिल करें

p = self.user.company.subdomain + ".rb" 
if File.exists?(Rails.root + "lib/" + p) 
include self.class.const_get(self.user.company.subdomain.capitalize.to_sym) 
    self.custom_add_url 
end 

मेरा परीक्षण मॉड्यूल इस तरह दिखता है:

module Companyx 
    def custom_add_url 
    puts "Calling custom_add_url" 
end 
end 

अब कंसोल में, यह वास्तव में ठीक काम करता है। मैं एक उपयोगकर्ता खींच और इतने की तरह मॉड्यूल शामिल कर सकते हैं:

[1] pry(main)> c = Card.find_by_personal_url("username") 
[2] pry(main)> include c.class.const_get(c.user.company.subdomain.capitalize)=> Object 
[3] pry(main)> c.custom_add_url 

कॉलिंग custom_add_url

अगर मैं अपने मॉडल से शामिल लाइन चलाने का प्रयास, मैं

NoMethodError: undefined method `include' for #<Card:0x007f91f9094fb0> 

किसी को भी बता सकते हैं क्यों शामिल कथन कंसोल पर काम करेगा, लेकिन मेरे मॉडल कोड में नहीं?

उत्तर

5

एक कक्षा में एक विधि शामिल है।

यदि आप इसे मॉडल के अंदर कॉल करना चाहते हैं, तो आपको कोड के सिंगलटन क्लास के संदर्भ में कोड निष्पादित करने की आवश्यकता है।

p = self.user.company.subdomain + ".rb" 
if File.exists?(Rails.root + "lib/" + p) 
myself = self 
class_eval do 
    include self.const_get(myself.user.company.subdomain.capitalize.to_sym) 
end 
self.custom_add_url 

संपादित करें:

वर्ग < < स्वयं एक ब्लॉक को स्वीकार नहीं करता; class_eval करता है, इसलिए यह स्थानीय चर की स्थिति को संरक्षित करता है। मैंने इसका उपयोग करने के लिए अपने समाधान को संशोधित कर दिया है।

+0

संदर्भ बदलना एक जटिलता को जोड़ता है: स्वयं ऑब्जेक्ट अस्तित्व में रहता है (या अधिक सटीक रूप से, उपयोगकर्ता ऑब्जेक्ट के साथ इसका सहयोग करता है)? मैंने इस पर काम करने के लिए विभिन्न तरीकों का प्रयास किया है और यह समझने के लिए इस आलेख को पढ़ा है कि यहां क्या हो रहा है (http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/) बिना सफलता के। –

+0

ओह, मेरा बुरा। असल में, नए संदर्भ में स्वयं वर्ग है। यह एक वर्ग eval करने के समान है। मैंने व्यक्तिगत परियोजना पर एक प्रयोग के रूप में ऐसा कुछ किया। इस फ़ाइल के शीर्ष में मदद करनी चाहिए: https://github.com/Hitonagashi/UndergroundFootball/blob/master/app/models/player।आरबी –

+0

मुझे यकीन नहीं है कि मैं समझता हूं: मुझे लगता है कि आप अपने कोड में प्रारंभिक विधि के बारे में बात कर रहे हैं, जहां आप गतिशील रूप से कक्षा विधियों के रूप में सभी संभावित कौशल जोड़ रहे हैं? मैं नहीं देखता कि यह मेरी समस्या पर कैसे लागू होता है, क्योंकि मैं कक्षा में एक संबद्ध वस्तु नहीं जोड़ सकता। कक्षा ब्लॉक के अंदर कोड के उदाहरण के संबंधों तक पहुंचने का कोई तरीका है? –

8

मैं एक जैसी चीज कर रहा हूं। मुझे यह उत्तर उपयोगी पाया गया: How to convert a string to a constant in Ruby?

बाहर निकलता है मैं निरंतर विधि की तलाश में था। इस लाइन मैं अपने कोड में उपयोग कर रहा हूँ है:

include "ModuleName::#{var.attr}".constantize 

संपादित करें:

तो पावती, मैं वास्तव में है कि रेखा अपने आप को उपयोग करने के साथ विभिन्न समस्याओं का सामना किया। आंशिक रूप से क्योंकि मैं इसे कक्षा में एक विधि के अंदर कॉल करने की कोशिश कर रहा था। लेकिन चूंकि मैं केवल कक्षा में एक विधि फोन कर रहा हूँ अंतिम कार्यरत वर्शन मैं अब,

"ModuleName::#{var.attr}".constantize.new.methodname 

जाहिर है methodName एक उदाहरण विधि है ताकि आप नए से छुटकारा पाने सकता है (जो कॉल/सब कुछ चलता है) अगर आपका एक वर्ग विधि है।

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