[英]Defining custom methods within a model/class in Rails 4
我有以下型號:
class ActivityLog < ActiveRecord::Base
validates :user_id, :instance_id, :action, presence: true
validates :user_id, :instance_id, :action, numericality: true
def log
ActivityLog.create(
user_id: current_user ? current_user.id : -1,
instance_id: instance_id,
action: actions.index(action)
)
end
private
def actions
['start','stop','create','destroy']
end
end
當我從rails控制台調用以下行時,出現錯誤:
ActivityLog.log(user_id: 1, instance_id:1, action: 'create')
# Error returned from console
NoMethodError: undefined method `log' for #<Class:0x007fb4755a26a8>
為什么我的方法調用不起作用? 我在課堂上定義了它,但它說它是未定義的。 我錯過了什么或誤解了什么? 謝謝。
log
假設您有一個類User
,並且在類中定義方法has_cell_phone
。 (該方法的內容無關緊要。)當您將類中的方法定義為def has_cell_phone
,可以在任何User
對象上調用該方法。 雖然class User
本身就是一個類對象,但您可以在其直接類為User
的對象上調用它。 正確地說,您將為User
類的實例編寫實例方法 。
您收到該錯誤,因為您定義的方法log
僅適用於ActivityLog
類的_instance。 如果執行以下操作,則可以根據當前代碼正確調用log
:
activity_log = ActivityLog.create # with required params
activity_log.log
其次,您使用參數調用log
,而您的方法定義不需要任何參數。 (這看起來像def log(params)
。)
現在,您可以在此處修改現有代碼。 如果要在整個類上調用方法(意味着類本身),則將關鍵字self
到類方法定義中。 例如,對於User
類,它將是def self.create_user_with_cell_phone
。 您還可以向該方法添加參數。 您在“方法調用”行中提供的參數,我會將它們添加到您的類方法中,如下所示:
def self.log(instance_id, action)
# ...
end
ActivityLog.log(1, 'create')
您不需要包含user_id
,因為根據您的邏輯,它會檢查current_user
對象是否為true
,並從那里開始。
再看看你的問題,我發現你正在定義一個方法actions
。 還記得我對實例方法的看法嗎? 由於看起來actions
總是保持不變,我建議你做一個! 為此,建議您在任何方法定義之前在類中放置以下行。
ACTIONS = ['start','stop','create','destroy']
然后,任何時候你要撥打ACTIONS
而內側ActivityLog
類,你做到以下幾點: ACTIONS.index(action)
。 如果你想在它的類之外調用這個常量,你可以這樣做: ActivityLog::ACTION
。 它與類方法調用的語法類似 ,而是使用::
將類與常量分開。 重新檢查您的代碼,現在應該如下所示:
class ActivityLog < ActiveRecord::Base
ACTIONS = ['start','stop','create','destroy']
validates :user_id, :instance_id, :action, presence: true
validates :user_id, :instance_id, :action, numericality: true
def self.log(instance_id, action)
ActivityLog.create(
user_id: (current_user ? current_user.id : -1),
instance_id: instance_id,
action: ACTIONS.index(action)
)
end
end
log
是定義的實例方法; 它只有在您擁有ActivityLog
的具體實例時才有效。
如果要將其作為類方法,則應通過self
關鍵字將其附加到類中。
def self.log
# code here
end
您正在編寫實例方法並將其稱為類方法。
要編寫類方法,需要在方法名稱之前添加self
( self.log
, self.actions
)。 這將讓你像預期的那樣調用方法,並且可能是編寫這樣的替代構造函數的最佳方法。 如果你的方法不依賴於類的特定實例,這似乎是你在這里做的,那么最好使它們成為類方法。
或者,您可以創建類的實例並調用已定義的實例方法。 而不是ActivityLog.log
,使用Activity.new
創建一個新的記錄器並在其上調用log方法。 在一行中,這看起來像Activity.new.log
,但您應該將新對象存儲在變量中以跟蹤它。
最后一種選擇是使用initialize
方法。 通過編寫def initialize
你改變構造函數的類,這樣不是調用ActivityLog.log
你可以調用ActivityLog.new
。 這使得您更清楚的是構建一個新對象並且在ruby中是慣用的。 但是,它確實刪除了描述性方法名稱。 如果你不打算用任何其他方法構建你的類,我會推薦這條路線,但是如果你想要幾個,請使用類方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.