在Rails 4中定义模型/类中的自定义方法

cjm*_*671 4 ruby ruby-on-rails class-method ruby-on-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
Run Code Online (Sandbox Code Playgroud)

当我从rails控制台调用以下行时,出现错误:

ActivityLog.log(user_id: 1, instance_id:1, action: 'create')

# Error returned from console
NoMethodError: undefined method `log' for #<Class:0x007fb4755a26a8>
Run Code Online (Sandbox Code Playgroud)

为什么我的方法调用不起作用?我在课堂上定义了它,但它说它是未定义的.我错过了什么或误解了什么?谢谢.

one*_*ree 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
Run Code Online (Sandbox Code Playgroud)

其次,您log使用参数调用,而您的方法定义不需要任何参数.(那看起来像def log(params).)

现在,您可以在此处修改现有代码.如果要在整个类上调用方法(意味着类本身),则将关键字添加self到类方法定义中.例如,对于User班级,它将是def self.create_user_with_cell_phone.您还可以向该方法添加参数.你在"方法调用"行中提供的参数,我会将它们添加到你的类方法中,如下所示:

def self.log(instance_id, action)
  # ...
end

ActivityLog.log(1, 'create')
Run Code Online (Sandbox Code Playgroud)

您不需要包含user_id,因为,根据您的逻辑,它会检查current_user对象是否是true,并从那里开始.

创建一个类常量

再看看你的问题,我发现你正在定义一个方法actions.还记得我对实例方法的看法吗?既然看起来actions总是保持不变,我建议你把它做成一个!为此,建议您在任何方法定义之前在类中放置以下行.

ACTIONS = ['start','stop','create','destroy']
Run Code Online (Sandbox Code Playgroud)

然后,只要你想ACTIONSActivityLog课堂上打电话,你就可以做到以下几点: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
Run Code Online (Sandbox Code Playgroud)