Attr_accessor और attr_accessible के बीच अंतर


235

रेल में, के बीच अंतर क्या है attr_accessorऔर attr_accessible? मेरी समझ से, attr_accessorउस वेरिएबल के लिए गेट्टर और सेटर विधियों को बनाने के लिए उपयोग किया जाता है, ताकि हम वैरिएबल को एक्सेस कर सकें जैसे Object.variableया Object.variable = some_value

मैंने वह पढ़ा जो attr_accessibleउस विशिष्ट चर को बाहरी दुनिया के लिए सुलभ बनाता है। क्या कोई मुझे बता सकता है कि अंतर क्या है


4
आप सही हैं जो attr_accessorगेट्टर और सेटर विधियों को उत्पन्न करने के लिए उपयोग किया जाता है। कृपया एक बहुत व्यापक स्पष्टीकरण के लिए मेरे पिछले प्रश्न का उत्तर देखें attr_accessible: stackoverflow.com/questions/2652907/… फिर उसके बाद किसी अन्य विशिष्ट विवरण की आवश्यकता होने पर अपने प्रश्न को अपडेट करें।
मिकज

2
attr_accessible नहीं रह रेल 4 में समर्थित है जब तक आप प्रति शीर्ष जवाब के रूप में करने के लिए, protected_attributes मणि का उपयोग stackoverflow.com/questions/17371334/... (जुलाई 2014)
एमरी

जवाबों:


258

attr_accessorएक रूबी विधि है जो एक गटर और एक सेटर बनाती है। attr_accessibleएक रेल विधि है जो आपको बड़े पैमाने पर असाइनमेंट के लिए मानों को पास करने की अनुमति देती है: new(attrs)या update_attributes(attrs)

यहाँ एक जन कार्य है:

Order.new({ :type => 'Corn', :quantity => 6 })

आप सोच सकते हैं कि ऑर्डर में डिस्काउंट कोड भी हो सकता है :price_off। आप टैग नहीं करते हैं :price_offके रूप में attr_accessibleतुम इतनी तरह ऐसा करने में सक्षम किया जा रहा से दुर्भावनापूर्ण कोड को रोकने:

Order.new({ :type => 'Corn', :quantity => 6, :price_off => 30 })

भले ही आपके फॉर्म में फ़ील्ड न हो :price_off, अगर यह आपके मॉडल में है तो यह डिफ़ॉल्ट रूप से उपलब्ध है। इसका मतलब है कि एक गढ़ा हुआ POST अभी भी इसे सेट कर सकता है। attr_accessibleसफेद का उपयोग उन चीजों को सूचीबद्ध करता है जिन्हें बड़े पैमाने पर सौंपा जा सकता है।


2
attr_accessibleरेल दस्तावेज में क्यों नहीं है? api.rubyonrails.org
क्लो

19
लगता है Rails4 चीजों को करने का एक नया तरीका है। इस उत्तर को देखें: stackoverflow.com/questions/17371334/…
पॉल रूबेल

1
क्योंकि मजबूत पैरामीटर ने attr_accessible किनारे के
इमरान अहमद

173

इस थ्रेड पर और Google पर बहुत से लोग बहुत अच्छी तरह से समझाते attr_accessibleहैं जो उन विशेषताओं के एक श्वेतसूची को निर्दिष्ट करता है जिन्हें बल्क में अपडेट करने की अनुमति है ( एक ही समय में एक ऑब्जेक्ट मॉडल के सभी गुण एक साथ ) यह आपके आवेदन की सुरक्षा के लिए मुख्य रूप से (और केवल) है "मास असाइनमेंट" से समुद्री डाकू का शोषण।

यह यहाँ रेल पटरियों पर समझाया गया है डॉक्टर: मास असाइनमेंट

attr_accessorएक रूबी कोड है (जल्दी से) एक कक्षा में सेटर और गेट्टर तरीके बनाएं। बस इतना ही।

अब, एक स्पष्टीकरण के रूप में जो याद आ रही है वह यह है कि जब आप डेटाबेस तालिका के साथ (रेल) मॉडल के बीच किसी तरह एक लिंक बनाते हैं, तो आपको attr_accessorअपने मॉडल में बसने और प्राप्त करने के लिए अपने मॉडल की आवश्यकता होती है, ताकि आप संशोधित कर सकें। तालिका के रिकॉर्ड।

ऐसा इसलिए है क्योंकि आपका मॉडल ActiveRecord::Baseक्लास से सभी तरीकों को विरासत में लेता है , जो पहले से ही आपके लिए बुनियादी सीआरयूडी एक्सेसर्स (क्रिएट, रीड, अपडेट, डिलीट) को परिभाषित करता है। इसे यहाँ के आधिकारिक दस्तावेज़ पर बताया गया है कि रेल्स मॉडल और यहाँ ओवर राइटिंग डिफॉल्ट एक्सेसर (अध्याय "ऑलराइट डिफॉल्ट एक्सेसर" पर स्क्रॉल करें)

उदाहरण के लिए कहें कि: हमारे पास "उपयोगकर्ता" नामक एक डेटाबेस तालिका है जिसमें तीन कॉलम "Firstname", "lastname" और "भूमिका" शामिल हैं:

SQL निर्देश:

CREATE TABLE users (
  firstname string,
  lastname string
  role string
);

मैंने मान लिया कि आपने config.active_record.whitelist_attributes = trueअपने एप्लिकेशन को मास असाइनमेंट शोषण से बचाने के लिए अपने config / environment / production.rb में विकल्प सेट किया है । यह यहाँ समझाया गया है: मास असाइनमेंट

आपके रेल मॉडल नीचे दिए गए मॉडल के साथ पूरी तरह से काम करेंगे:

class User < ActiveRecord::Base

end

हालाँकि आपको अपने प्रपत्र के कार्य के लिए अपने नियंत्रक में उपयोगकर्ता की प्रत्येक विशेषता को अलग से अपडेट करना होगा:

def update
    @user = User.find_by_id(params[:id])
    @user.firstname = params[:user][:firstname]
    @user.lastname = params[:user][:lastname]

    if @user.save
        # Use of I18 internationalization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

अब अपने जीवन को आसान बनाने के लिए, आप अपने उपयोगकर्ता मॉडल के लिए एक जटिल नियंत्रक नहीं बनाना चाहते हैं। तो आप attr_accessibleअपने क्लास मॉडल में विशेष विधि का उपयोग करेंगे :

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname

end

तो आप अद्यतन करने के लिए "राजमार्ग" (बड़े पैमाने पर असाइनमेंट) का उपयोग कर सकते हैं:

def update
    @user = User.find_by_id(params[:id])

    if @user.update_attributes(params[:user])
        # Use of I18 internationlization t method for the flash message
        flash[:success] = t('activerecord.successful.messages.updated', :model => User.model_name.human)
    end

    respond_with(@user)
end

आपने attr_accessibleसूची में "भूमिका" विशेषताओं को नहीं जोड़ा क्योंकि आप अपने उपयोगकर्ताओं को अपनी भूमिका स्वयं निर्धारित करने नहीं देते (जैसे व्यवस्थापक)। आप इसे स्वयं किसी अन्य विशेष व्यवस्थापक दृश्य पर करते हैं।

यद्यपि आपका उपयोगकर्ता दृश्य "भूमिका" फ़ील्ड नहीं दिखाता है, लेकिन एक समुद्री डाकू आसानी से एक HTTP POST अनुरोध भेज सकता है जिसमें परमेस हैश में "भूमिका" शामिल है। अनुपलब्ध "भूमिका" विशेषता attr_accessibleआपके एप्लिकेशन को उससे बचाने के लिए है।

आप अभी भी नीचे की तरह अपने user.role विशेषता को संशोधित कर सकते हैं, लेकिन सभी विशेषताओं के साथ एक साथ नहीं।

@user.role = DEFAULT_ROLE

आप नरक का उपयोग क्यों करेंगे attr_accessor?

ठीक है, यह इस मामले में होगा कि आपका उपयोगकर्ता-प्रपत्र एक फ़ील्ड दिखाता है जो आपके उपयोगकर्ताओं की तालिका में स्तंभ के रूप में मौजूद नहीं है।

उदाहरण के लिए, मान लें कि आपका उपयोगकर्ता दृश्य "कृपया-बताएं-व्यवस्थापक-कि-मैं-मैं-में-यहाँ" फ़ील्ड दिखाता हूं। आप इस जानकारी को अपनी तालिका में संग्रहीत नहीं करना चाहते हैं। आप बस इतना चाहते हैं कि रेल आपको एक ई-मेल चेतावनी भेजती है कि एक "पागल" ;-) उपयोगकर्ता ने सदस्यता ली है।

इस जानकारी का उपयोग करने में सक्षम होने के लिए आपको इसे अस्थायी रूप से कहीं स्टोर करने की आवश्यकता है। एक user.peekabooविशेषता में इसे पुनर्प्राप्त करने से ज्यादा आसान क्या है ?

इसलिए आप इस क्षेत्र को अपने मॉडल में जोड़ें:

class User < ActiveRecord::Base

  attr_accessible :firstname, :lastname
  attr_accessor :peekaboo

end

तो आप user.peekabooई-मेल भेजने के लिए या अपने मनचाहे काम को करने के लिए कहीं न कहीं अपने नियंत्रक में विशेषता का एक शिक्षित उपयोग कर पाएंगे ।

जब आप ऐसा करते हैं तो ActiveRecord आपकी तालिका में "picaboo" विशेषता को नहीं बचाएगा, user.saveक्योंकि वह अपने मॉडल में इस नाम से मेल खाते कोई कॉलम नहीं देखती है।


48

attr_accessorएक रूबी विधि है जो आपको एक ही नाम के उदाहरण चर के लिए सेटर और गेट्टर तरीके देती है। तो यह बराबर है

class MyModel
  def my_variable
    @my_variable
  end
  def my_variable=(value)
    @my_variable = value
  end
end

attr_accessible एक रेल विधि है जो यह निर्धारित करती है कि बड़े पैमाने पर असाइनमेंट में कौन से चर सेट किए जा सकते हैं।

जब आप एक फॉर्म जमा करते हैं, और आपके पास कुछ ऐसा होता है, MyModel.new params[:my_model]तो आप थोड़ा और अधिक नियंत्रण रखना चाहते हैं, ताकि लोग उन चीजों को जमा न कर सकें जो आप उन्हें नहीं चाहते हैं।

आप ऐसा attr_accessible :emailकर सकते हैं कि जब कोई अपना खाता अपडेट करता है, तो वे अपना ईमेल पता बदल सकते हैं। लेकिन आप ऐसा नहीं करेंगे attr_accessible :email, :salaryक्योंकि तब एक व्यक्ति फॉर्म जमा करने के माध्यम से अपना वेतन निर्धारित कर सकता है। दूसरे शब्दों में, वे अपना रास्ता हैक करने के लिए कर सकते हैं।

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

तो attr_accessorचर को स्टोर करने के तरीके बनाने के बारे में है, और attr_accessibleबड़े पैमाने पर असाइनमेंट की सुरक्षा के बारे में है।


2
आपके पास एक टाइपो है, कोड ब्लॉक के बाद यह कहना चाहिएattr_accesible
चुबस

महान लेखन, मुझे कक्षा उदाहरण पसंद है। के स्पष्टीकरण के लिए अतिरिक्त (नकली) बोनस अंक :as!
इयान वॉन

मॉडल ActiveRecord :: Base द्वारा विस्तारित है। class User < ActiveRecord::Base
ग्रीन

18

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

आइए निम्नलिखित उदाहरण पर विचार करें

class Address
    attr_reader :street
    attr_writer :street  
    def initialize
        @street = ""
    end
end

यहाँ हमने उद्देश्य को प्राप्त करने के लिए attr_reader( पठनीय विशेषता ) और attr_writer( लेखन योग्य विशेषता ) का उपयोग किया है। लेकिन हम उसी कार्यक्षमता का उपयोग करके प्राप्त कर सकते हैं attr_accessor। संक्षेप में, attr_accessor गेट्टर और सेटर दोनों तरीकों तक पहुँच प्रदान करता है।

इसलिए संशोधित कोड नीचे दिया गया है

class Address
    attr_accessor :street  
    def initialize
        @street = ""
    end
end

attr_accessibleआपको उन सभी स्तंभों को सूचीबद्ध करने की अनुमति देता है जिन्हें आप मास असाइनमेंट की अनुमति देना चाहते हैं। इसके विपरीत attr_protectedजिसका अर्थ है कि यह क्षेत्र मैं नहीं चाहता कि किसी को भी मास असाइन करने की अनुमति दी जाए। संभावना से अधिक यह आपके डेटाबेस में एक क्षेत्र होने जा रहा है कि आप किसी को भी अपने साथ बंदर नहीं करना चाहते हैं। जैसे कोई स्टेटस फील्ड, या लाइक।


2
तो क्या आप यह कह रहे हैं कि अगर मैंने एक माइग्रेशन में फ़ील्ड बनाए हैं, तो उन्हें attr_accessible का उपयोग करके उपलब्ध कराएं, तो गेट्टर और सेटर बनाने की कोई आवश्यकता नहीं है? लेकिन यदि क्षेत्र डेटाबेस में नहीं है, तो कैसे आना / पहुंच योग्य नहीं है एक गेटर / सेटर की तरह कार्य करता है? यदि मैं एक पंक्ति "has_secure_password" शामिल करता हूं, तो attr_accessible गेट्टर / सेटर को पासवर्ड और: password_confirmation की अनुमति देने के लिए पर्याप्त हो जाता है, भले ही वे डेटाबेस में न हों। बहुत उलझन में;)
तम्बू

2

दो शब्दों में:

attr_accessorहै getter, setterविधि। जबकि attr_accessibleयह कहना है कि विशेष गुण सुलभ है या नहीं। बस।


मैं यह जोड़ना चाहता हूं कि हमें सामूहिक आक्रोश से बचाने के लिए मजबूत पैरामीटर का उपयोग करना चाहिए attr_accessible

चीयर्स!


2

एक त्वरित और संक्षिप्त अंतर अवलोकन:

attr_accessorअपनी कक्षा में एक्सेसर्स को पढ़ने और लिखने का एक आसान तरीका है। इसका उपयोग तब किया जाता है जब आपके डेटाबेस में कोई कॉलम नहीं होता है, लेकिन फिर भी आप अपने फॉर्म में फ़ील्ड दिखाना चाहते हैं। यह फ़ील्ड “virtual attribute”एक रेल मॉडल में है।

आभासी विशेषता - डेटाबेस में कॉलम के अनुरूप विशेषता नहीं है।

attr_accessible का उपयोग उन विशेषताओं की पहचान करने के लिए किया जाता है जो आपके नियंत्रक विधियों द्वारा सुलभ हैं, बड़े पैमाने पर असाइनमेंट के लिए एक संपत्ति उपलब्ध कराती हैं .. यह केवल उन विशेषताओं तक पहुंच की अनुमति देगा जो आप निर्दिष्ट करते हैं, बाकी को नकारते हुए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.