簡體   English   中英

在Rails 4中定義模型/類中的自定義方法

[英]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

您正在編寫實例方法並將其稱為類方法。

要編寫類方法,需要在方法名稱之前添加selfself.logself.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM