繁体   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