2015-10-20 147 views
2

我研究了Ruby類,實例方法和主要區別之間的主要區別,我發現我們不需要創建該類的實例,我們可以直接在類名上直接調用該方法。Ruby on Rails實例vs類方法

class Notifier 

def reminder_to_unconfirmed_user(user) 
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}' 
    @user = user 
    mail(:to => @user["email"], :subject => "confirmation instructions reminder") 
    end 

end 

所以,在這裏我在Notifier類中定義的實例方法reminder_to_unconfirmed_user發送電子郵件未經證實的用戶,當我運行Notifier.reminder_to_unconfirmed_user(User.last)它被調用提供了它的一個實例方法不是一個類的方法。

+1

問題是什麼? – Meier

+0

他的問題是爲什麼可以在類上調用實例方法,就好像它是類方法一樣。在下面發佈答案。 – bkunzi01

回答

4

要定義一個類的方法,使用該方法的定義self關鍵字(或類的名稱):

class Notifier 
    def self.this_method_is_a_class_method 
    end 

    def Notifier.this_one_is_a_class_method_too 
    end 

    def this_method_is_an_instance_method 
    end 
end 

在你的情況,reminder_to_unconfirmed_user應該被定義爲一個類的方法:

class Notifier 

    def self.reminder_to_unconfirmed_user(user) 
    # ... 
    end 

end 

然後你可以使用它像這樣:

Notifier.reminder_to_unconfirmed_user(User.last) 
0

在你的情況下,它必須是:

class Notifier 

    def self.reminder_to_unconfirmed_user(user) 
    headers['X-SMTPAPI'] = '{"category": "confirmation_reminder"}' 
    @user = user 
    mail(:to => @user["email"], :subject => "confirmation instructions reminder") 
    end 

end 

顧名思義:

模型上的實例方法應該用於那些涉及模型的特定實例的邏輯/操作(一個該方法稱爲)

類方法適用於不在模型的單個實例上運行的情況,或者在您沒有實例可用的情況下。就像在某些情況下,您確實想對少數幾組對象應用更改。 如果您想要更新特定條件下的所有用戶,那麼您應該去上課方法。

他們也有打電話的方式不同:

class Test 
    def self.hi 
    puts 'class method' 
    end 

    def hello 
    puts 'instance method' 
    end 
end 

Foo.hi # => "class method" 
Foo.hello # => NoMethodError: undefined method ‘hello’ for Test:Class 

Foo.new.hello # => instance method 
Foo.new.hi # => NoMethodError: undefined method ‘hi’ for #<Test:0x1e871> 
0

我有OP也做了同樣的問題,周圍挖後,我終於想通了!其他答案只是解決了什麼時候在Ruby中使用實例vs類方法,但Rails在場景後面做了一些鬼鬼祟祟的東西。問題不在於什麼時候使用類和實例方法,而是Rails如何允許您調用實例方法,就好像它是上面的郵件程序示例所示的類方法。這是由於:AbstractController::Base,可以在這裏看到:AbstractController::Base

基本上,所有控制器(無論是你的郵件或標準控制器),所有定義的方法是通過「method_missing的」截獲,然後返回一個類的實例!然後定義的方法也轉換爲公共實例方法。因此,因爲你永遠不會實例化這些類(例如你永遠不會做Mailer.new.some_method),Rails自動調用method_missing並返回該Mailer的一個實例,然後利用該類中定義的所有方法。