2009-05-14 6 views
13

में self.method_name बनाम classname.method_name के उपयोग को समझने का प्रयास कर रहा है। मैं classname.method_name का उपयोग करने के लिए self.method_name बनाम कब उपयोग करना है, यह समझने की कोशिश कर रहा हूं।रूबी

नीचे दिए गए उदाहरण में, "self_create" को "self.hash_password" या बस "हैश_पासवर्ड" के बजाय "User.hash_password" को संदर्भित करने की आवश्यकता क्यों है?

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

require 'digest/sha1' 

class User < ActiveRecord::Base 

    attr_accessor :password 
    attr_accessible :name, :password 

    validates_presence_of :name, :password 
    validates_uniqueness_of :name 

    def before_create 
    self.hashed_password = User.hash_password(self.password) 
    end 

    def after_create 
    @password = nil 
    end 

    def self.login(name, password) 
    hashed_password = hash_password(password || "") 
    self.find(:first, :conditions => ["name = ? and hashed_password = ?", name, hashed_password]) 
    end 

    def try_to_login 
    User.login(self.name, self.password) 
    end 

    private 

    def self.hash_password(password) 
    Digest::SHA1.hexdigest(password) 
    end 

end 

उत्तर

13
def before_create 
    self.hashed_password = User.hash_password(self.password) 
end 

इस उदाहरण में, User.hash_password कॉल पर hash_password विधि वर्गUser, self.hashed_password=इस विशेष उदाहरण User की पर कॉल जबकि hashed_password= विधि।

आप self.hash_password साथ User.hash_password बदलते हैं, रूबी, एक NoMethodError साथ शिकायत क्योंकि hash_password के नाम से कोई उदाहरण विधि वर्ग User में मौजूद होगा। हालांकि, आप self.class.hash_password के साथ इसे प्रतिस्थापित कर सकते हैं।

आप बस hashed_password= साथ self.hashed_password= बदलते हैं, रूबी एक स्थानीय hashed_password नामित चर बना होता है, बजाय उदाहरण विधि hashed_password= कहते हैं। यदि आप विशेषता लेखकों को कॉल करना चाहते हैं तो आपको स्पष्ट रूप से self जोड़ना होगा।

विधि परिभाषा में self (def self.hash_password) hash_password एक उदाहरण विधि के बजाय एक क्लास विधि बनाता है। इस संदर्भ में, selfवर्ग को संदर्भित करता है। एक उदाहरण विधि के संदर्भ में, selfउदाहरण को संदर्भित करता है।

+0

कहा जाता है क्योंकि अंतिम कुछ पंक्तियां def self.hash_password (पासवर्ड) को परिभाषित करती हैं, मैंने सोचा कि self.hash_password इस विधि को संदर्भित करता है। लेकिन आप स्वयं कह रहे हैं ..hash_password को NoMethodError मिलेगा - भले ही विधि परिभाषा "स्वयं" कहती है। मैं इसे "स्वयं" के साथ संदर्भित नहीं कर सकता। भ्रामक! –

+0

self.hashed_password = एक विशेषता लेखक को कॉल करता है? लेकिन मैंने एक विशेषता लेखक को परिभाषित नहीं किया। क्या स्वचालित रूप से बनाया गया था? –

+0

self.hashed_password = शायद आपके लिए ActiveRecord द्वारा परिभाषित किया गया है, यदि आपके पास 'हैशड_पासवर्ड' नामक डेटाबेस कॉलम है। – molf

1

मैं रूबी में तल्लीन करने के लिए अभी तक है, लेकिन अपने वर्णन से मैं कहना चाहता हूँ कि hash_password एक स्थिर तरीका है या एक स्थिर तरीके से इस्तेमाल किया जा रहा करने में सक्षम है।

+3

यह सही है। रूबी में, स्थैतिक विधि को कक्षा विधियों –

12

आप कक्षा विधि और एक उदाहरण विधि के बीच अंतर पूछ रहे हैं।

class Klass 
    def Klass.method_name 
    .. 
    end 
end 

जो कर के रूप में ही है:

class Klass 
    def self.method_name 
    .. 
    end 
end 

या पसंदीदा रूबी मुहावरा:

class Klass 
    class << self 
    def method_name 
     .. 
    end 
    end 
end 

तो

वहाँ एक वर्ग विधि को परिभाषित करने के कुछ तरीके हैं Klass पहले से ही घोषित किया गया है कि आप भी कर सकते हैं ..

def Klass.method_name 
    .. 
end 

या:

class << Klass 
    def method_name 
    .. 
    end 
end 

या तुम भी मॉड्यूल # इस्तेमाल कर सकते हैं का विस्तार:

Klass.extend(Module.new { def method_name; puts 'ducky'; end }) 

बहुत आप की तरह किसी ऑब्जेक्ट को सिंगलटन विधि जोड़ना होगा। वास्तव में कक्षा के तरीके सिंगलटन विधियां हैं जो कक्षा स्तर पर संचालित होती हैं।

में रेल ActiveRecord उदाहरण के लिए यदि आप एक वर्ग विधि 'खोज' जो आप किसी भी मॉडल पर उपयोग कर सकते हैं:

Person.find(1) 

और उदाहरण तरीकों 'सहेजें' जो व्यक्ति वस्तु पर चल रही है की तरह

person = Person.find(1) 
... 
person.save 

वर्तमान प्रोजेक्ट में मैं काम कर रहा हूं मेरे पास एक मॉडल फीड है जिसमें डेटा फ़ीड्स हैं। समय-समय पर मुझे एक विधि चलाने की ज़रूरत होती है जो सभी फीड अपडेट करता है, इसलिए मेरे पास fetch_all विधि है जो इसे पूरा करती है।

class Feed < ActiveRecord::Base 

    // class method Feed.fetch_all 
    def self.fetch_all 
    Feed.all.each do |feed| 
     feed.fetch_value 
    end 
    end 

    // instance method 
    def fetch_value 
    // grabs updated value and saves 
    end 
end