2010-11-16 13 views
13

मैं मॉडल में इस का उपयोग करके कुछ मॉडलों के लिए अद्यतन किया गया है को रोकने:मैं एक फ़ील्ड को छोड़कर अपडेट को कैसे अस्वीकार कर सकता हूं?

def update 
    self.errors.add_to_base("Cannot update a #{ self.to_s }") 
end 

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

def update 
    if self.changed == ['my_field'] 
    super 
    else 
    self.errors.add_to_base("Cannot update a #{ self.to_s }")  
    end 
end 

मैं अपने प्लगइन से ही ऐसा नहीं कर सकते क्योंकि मैं अगर अद्यतन व्यवहार ActiveRecord डिफ़ॉल्ट है पता नहीं है , या अद्यतनों को रोकने के लिए ओवरराइड किया गया है। क्या मुझे एक विशिष्ट फ़ील्ड के लिए ओवरराइड करने की अनुमति देते हुए रिकॉर्ड अपडेट को रोकने का एक और तरीका है (और केवल उस उदाहरण में जहां मेरी प्लगइन इस मॉडल पर लागू होती है)।

उत्तर

10

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

attr_accessor :updatable_attributes 
    before_update :prevent_update 

    private 
    def prevent_update 
    return true if self.changed == self.updatable_attributes 
    self.errors.add_to_base "Cannot update a #{ self.to_s }" 
    false 
    end 
end 
+0

धन्यवाद। मुझे एहसास हुआ कि जिन मॉडलों को मेरे prevent_update तर्क की आवश्यकता है वे भी प्लगइन की आवश्यकता है, इसलिए मैंने सुझाव दिया है कि पहले_update फ़िल्टर का उपयोग करके, मैंने प्लगइन में पूरी तरह से स्थानांतरित कर दिया है। – Nick

+4

रेल में 3. *, 'self.errors.add: बेस के माध्यम से त्रुटि जोड़ें, "अपडेट नहीं किया जा सकता ..." ' – ronen

+1

मुझे लगता है कि आप शायद चाहते हैं कि अगर क्लॉज स्वयं को वापस कर दिया जाए तो स्वयं को वापस कर दें। updateatabale_attributes == self.updatabale_attributes' ताकि आप updatable_attributes के सबसेट को भी अपडेट कर सकें। – Timo

0

क्या यह बड़े पैमाने पर असाइनमेंट को रोकने के लिए है? क्या आपको चाहिए जो attr_accessible/attr_ संरक्षित नहीं है?


संपादित करें, बस कॉलबैक के बारे में सामान्य बिंदु को चित्रित करने के लिए संपादित करें।

module MyModule 
    def MyModule.included(base) 
    base.send :alias_method_chain, :prevent_update, :exceptions 
    end 

    def prevent_update_with_exceptions 
    end 
end 

class MyModel < ActiveRecord::Base 
    before_validation :prevent_update 

    def prevent_update 
    end 

    include MyModule 
end 
+0

नहीं, यह मॉडल स्तर पर व्यावसायिक नियमों को लागू करने के लिए है। प्रत्येक क्षेत्र के लिए attr_readonly करना एक को छोड़कर काम कर सकता है, लेकिन वर्बोज़ है। – Nick

+0

पहले_विधीकरण कॉलबैक के बारे में कैसे? आप जांच सकते हैं कि कौन से गुण बदल गए हैं और यदि मॉडल नया है, और फिर अद्यतन को रोकें? – allan

+0

सुनिश्चित नहीं है कि मैं आपके सुझाव को पूरी तरह से समझता हूं ... आप मॉडल में पहले_विधीकरण कॉलबैक जोड़ने के लिए कह रहे हैं जो अपडेट को रोक देगा। फिर मेरी प्लगइन में मुझे एक फ़ील्ड पर अपडेट की अनुमति देने के लिए क्या करना चाहिए? – Nick

4

देर खेल यहाँ करने के लिए, लेकिन लोगों को इस सवाल को देखने के लिए, आप attr_readonly उपयोग कर सकते हैं बनाने पर एक क्षेत्र के लिए लिख, लेकिन अद्यतन की अनुमति नहीं दे अनुमति देने के लिए।

http://api.rubyonrails.org/classes/ActiveRecord/ReadonlyAttributes/ClassMethods.html

देखें मुझे लगता है कि यह रेल बाद से उपलब्ध है 2.0

मुश्किल हिस्सा है, अगर आप किसी भी गुण सूची हैं कि attr_accessible आप अपने केवल पढ़ने के लिए वहाँ भी जिम्मेदार बताते है (या आप प्राप्त बनाने पर एक जन असाइनमेंट त्रुटि):

class Post < ActiveRecord::Base 
    attr_readonly :original_title 
    attr_accessible :latest_title, :original_title 
end 
+0

mdkirby, क्या आप इस पर एक नज़र डाल सकते हैं? मुझे लगता है कि यह इस जवाब से जुड़ा हुआ है। http://stackoverflow.com/questions/33357501/rails-attribute-changes-in-spite-of-not-being-in-form –

0

मैं सिर्फ रेल श्वेतसूची में params.require विधि जिम्मेदार बताते हैं कि आप अनुमति देना चाहते का उपयोग करें।

def update 
    if @model.update(update_model_params) 
    render json: @model, status: :ok 
    else 
    render json: @model.errors, status: :unprocessable_entity 
    end 
end 

private 
    def update_prediction_params 
    params.require(:model).permit(:editable_attribute) 
    end 
संबंधित मुद्दे

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