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