我有以下型号:
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>
为什么我的方法调用不起作用?我在课堂上定义了它,但它说它是未定义的。我错过了什么或误解了什么?谢谢。
答案 0 :(得分:9)
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
答案 1 :(得分:2)
log
是定义的实例方法;它只有在你拥有ActivityLog
的具体实例时才有效。
如果你想把它作为一个类方法,你应该通过self
关键字将它附加到课堂上。
def self.log
# code here
end
答案 2 :(得分:0)
您正在编写实例方法并将其称为类方法。
要编写类方法,您需要在方法名称(self
,self.log
)之前添加self.actions
。这将让你像预期的那样调用方法,并且可能是编写这样的替代构造函数的最佳方法。如果你的方法不依赖于类的特定实例,这似乎是你在这里做的,那么最好使它们成为类方法。
或者,您可以创建类的实例并调用已定义的实例方法。使用ActivityLog.log
创建一个新的记录器而不是Activity.new
,并在其上调用log方法。在一行中,这看起来像Activity.new.log
,但您应该将新对象存储在变量中以跟踪它。
最后一种选择是使用initialize
方法。通过撰写def initialize
,您可以更改班级的构造函数,这样您就可以调用ActivityLog.log
而不是调用ActivityLog.new
。这使得您更清楚的是构建一个新对象并且在ruby中是惯用的。但是,它确实删除了描述性方法名称。如果你不打算用任何其他方法构建你的类,我会推荐这条路线,但是如果你想要几个,那就去使用类方法。