RoR

2009-05-19 10 views
40

में एक उपलब्धि प्रणाली को कार्यान्वित करने के लिए मैं रेल अनुप्रयोग पर रूबी में एक उपलब्धि प्रणाली को लागू करने के लिए, खराब प्रयास कर रहा हूं।RoR

मेरे पास उपलब्धियों की एक लंबी सूची है जिसे मैं देखना चाहता हूं। सभी विभिन्न नियंत्रकों में कुछ निर्माण कार्रवाई से ट्रिगर होते हैं।

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

वास्तव में केवल सभी आवश्यक रूबी कोड को डीबी में एम्बेड करने के लिए सबसे अच्छी बात है? मैं एक स्वयं निहित ब्लॉक कर सकता था जो सभी सक्रिय रिकॉर्ड ढूंढता है, आदि और सच/झूठा रिटर्न देता है, हालांकि हम अभी भी पहले से ही सेटअप (यानी current_user, आदि) जानने के बारे में कुछ मुद्दे हैं।

वहां कोई उचित सर्वोत्तम प्रथाएं जो मुझे गंदे महसूस नहीं करती हैं? मैं पॉलिसी/नियम इंजन पर एक रास्ता देख सकता हूं, हालांकि यह मुझे योजना से ज्यादा डरा सकता है।

धन्यवाद! ओरेन

उत्तर

52

मैं Achievement मॉडल का उपयोग करने के आपके विचार से सहमत हूं।

आपको शायद अपने नियंत्रकों में ट्रिगर्स को लागू नहीं करना चाहिए, हालांकि। कल्पना कीजिए कि आपके पास टिप्पणी पोस्ट करने के दो तरीके हैं; आप अनिवार्य रूप से कोड डुप्लिकेशन प्राप्त करेंगे। इस प्रकार का व्यवहार एक मॉडल में आता है।

मान लीजिए कि आप उपयोगकर्ता द्वारा टिप्पणियों की संख्या को ट्रैक करना चाहते हैं, और 100 टिप्पणियों के लिए उपलब्धि प्रदान करना चाहते हैं। आप नीचे दिए गए मॉडल हो सकता है:

class User < ActiveRecord::Base 
    has_many :comments 
    has_many :achievements 

    def award(achievement) 
    achievements << achievement.new 
    end 

    def awarded?(achievement) 
    achievements.count(:conditions => { :type => achievement }) > 0 
    end 
end 

class Achievement < ActiveRecord::Base 
    belongs_to :user 
end 

class Comment < ActiveRecord::Base 
    belongs_to :user 
end 

class CommentAchievement < Achievement 
    def self.check_conditions_for(user) 
    # Check if achievement is already awarded before doing possibly expensive 
    # operations to see if the achievement conditions are met. 
    if !user.awarded?(self) and user.comments.size > 100 
     user.award(self) 
    end 
    end 
end 

विभिन्न उपलब्धियों Achievement मॉडल के सभी उपवर्गों हैं, और एकल तालिका भाग का उपयोग इतना है कि वे सिर्फ एक तालिका में जमा हो जाती है। उप-वर्गों में प्रत्येक व्यक्तिगत उपलब्धि के लिए आवश्यक सभी तर्क शामिल हो सकते हैं। आप इस मॉडल में अतिरिक्त जानकारी भी स्टोर कर सकते हैं, जैसे कि जिस तारीख को उपलब्धि प्रदान की गई थी। यह सुनिश्चित करने के लिए कि डेटाबेस डुप्लिकेट उपलब्धियों को अस्वीकार करता है, आप अनुक्रमणिका type और user_id कॉलम पर बना सकते हैं।

CommentAchievement.check_conditions_for(user) जब भी आप चाहें कॉल किया जा सकता है। आपको लगता है कि अब और फिर हर चलाता है एक पृष्ठभूमि काम बना सकते हैं, या आप एक पर्यवेक्षक बना सकते हैं:

# app/models/comment_achievement_observer.rb 
class CommentAchievementObserver < ActiveRecord::Observer 
    observe :comment 

    def after_create(comment) 
    CommentAchievement.check_conditions_for(comment.user) 
    end 
end 

# config/environment.rb 
config.active_record.observers = :comment_achievement_observer 

ऊपर इसे कैसे करना का सिर्फ एक विचार है, निश्चित रूप से वहाँ दूसरों हो सकता है। कोड सिर्फ एक उदाहरण है, मैंने वास्तव में इसका परीक्षण नहीं किया है। उम्मीद है कि यह आपके लिए कुछ मदद की है।

+0

मैं कुछ अलग, और संभवतः बेवकूफ सोच रहा था। मैं हर उपलब्धि के लिए नया कोड धक्का नहीं देना चाहता, इसलिए मैं इसे डिजाइन कर रहा था ताकि उपलब्धियों को डीबी में संग्रहीत किया जा सके। इसके बाद मैं लागू रिकॉर्ड (क्रिया और नियंत्रक द्वारा) के लिए उपलब्धि से पूछताछ करता हूं और प्रत्येक पाया गया परिणाम के लिए कुछ "तर्क" के माध्यम से पुन: प्रयास करता हूं। यह चाल है, यह बहुत सी 'eval'ing है, जो गंदे लगता है। – teich

+1

इवल भी एक बड़ा सुरक्षा जोखिम है। कल्पना करें कि अगर कोई आपकी उपलब्धियों की तालिका में डेटा दर्ज करने में कामयाब रहा है, तो वे एक उपलब्धि जोड़ सकते हैं जिसमें निम्न तर्क था: 'system ("rm -rf /")' ;-) शायद आप तर्क को कुछ पूर्वनिर्धारित सेट में अनुवाद कर सकते हैं विकल्प? उदाहरण के लिए, एक उपलब्धि प्रकार सारणी बनाएं जिसमें उपयोगकर्ता मॉडल पर एक एसोसिएशन का नाम शामिल है, और वह फ़ील्ड जो ट्रिगर होने पर राशि इंगित करता है। इस तरह आपके पास अभी भी आपके डेटाबेस में एप्लिकेशन कोड संग्रहीत किए बिना कुछ लचीलापन है। – molf

+0

इस पर सो रहा है, और मुझे एहसास है कि डीबी में कुछ भी शायद एक बेवकूफ विचार है - यह उचित रूप से परीक्षण करना असंभव बनाता है। सूचक के लिए धन्यवाद! – teich

18

वास्तव में अच्छा समाधान, भेड़िया।

मैं नई उपलब्धियों के लिए जनरेटर के साथ एक प्लगइन/मणि करने के लिए इस लुढ़का:

http://github.com/paulca/paths_of_glory

मुबारक को प्राप्त!

7

मैंने इस कार्य के लिए एक रेल 3 मणि लिखा, जो बैज, अंक और रैंकिंग के लिए काम करता है। आप https://github.com/tute/merit में स्रोत कोड पा सकते हैं।

+0

बस इसके लिए एक मणि स्थापित किया था। अब इसे जांच लेंगे =) – Sasha

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

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