Ruby:我可以在类方法中使用实例方法吗?

时间:2022-11-25 00:28:52

I have a class that contains this class method:

我有一个包含这个类方法的类:

def self.get_event_record(row, participant)
  event = Event.where(
      :participant_id   => participant.id,
      :event_type_code  => row[:event_type],
      :event_start_date => self.format_date(row[:event_start_date])
  ).first

  event = Event.new(
      :participant_id   => participant.id,
      :event_type_code  => row[:event_type],
      :event_start_date => self.format_date(row[:event_start_date])
  ) if event.blank?

  event
end

And I also have, in the same class, an instance method:

而且我在同一个类中也有一个实例方法:

def format_date(date)
  parsed_date = date.split('/')

  # if month or day are single digit, make them double digit with a leading zero
  if parsed_date[0].split("").size == 1
    parsed_date[0].insert(0, '0')
  end
  if parsed_date[1].split("").size == 1
    parsed_date[1].insert(0, '0')
  end

  parsed_date[2].insert(0, '20')

  formatted_date = parsed_date.rotate(-1).join("-")
  formatted_date
end

I'm getting an 'undefined method' error for #format_date. (I tried it without the self in front, at first). Can you not use instance methods in class methods of the same class?

我为#format_date收到了“未定义的方法”错误。 (我在前面没有自我的情况下尝试过它,起初)。你能不能在同一个类的类方法中使用实例方法?

3 个解决方案

#1


23  

Short answer is no, you cannot use instance methods of a class inside a class method unless you have something like:

简短的回答是否定的,你不能在类方法中使用类的实例方法,除非你有类似的东西:

class A
  def instance_method
    # do stuff
  end

  def self.class_method
     a = A.new
     a.instance_method
  end
end

But as far as I can see, format_date does not have to be an instance method. So write format_date like

但据我所知,format_date不一定是实例方法。所以写format_date就好

def self.format_date(date)
   # do stuff
end

#2


4  

Just create class method

只需创建类方法

def self.format_date (..)
  ...
end

And if u need instance method, delegate it to class method

如果你需要实例方法,请将它委托给类方法

def format_date *args
  self.class.format_date *args
end

And i don't think that it is good idea to call instance methods from class scope

我不认为从类范围调用实例方法是个好主意

#3


3  

You could do YourClassName.new.format_date(your_date), although I think it's pretty clear you should be restructuring your code - this method probably doesn't belong on an instance. Why don't you extend the Date Class, or make format_date a class method on the class you are using?

你可以做YourClassName.new.format_date(your_date),虽然我认为很明显你应该重构你的代码 - 这个方法可能不属于实例。为什么不扩展Date类,或者将format_date作为您正在使用的类的类方法?

EDIT: Here are a few other things to think about with your code:

编辑:以下是您需要考虑的其他一些事项:

  • Your whole format_date method goes to a lot of lengths to manipulate dates as strings. Why not use Ruby's Date Class? Using Date.parse or Date.strptime or even "01/01/2001".to_date might be useful depending on your locale
  • 你的整个format_date方法花了很多篇幅来操作日期作为字符串。为什么不使用Ruby的Date类?使用Date.parse或Date.strptime甚至“01/01/2001”.to_date可能很有用,具体取决于您的语言环境
  • Consider extending the String class for your method, if you really need to make your own method:

    如果您确实需要创建自己的方法,请考虑为您的方法扩展String类:

    class String
      def to_friendly_formatted_date
        Date.strptime(self, "%d/%m/%y")
      end
    end
    "01/08/09".to_friendly_formated_date
    
  • Your class method is crying our for the find_or_initialize_by helper methods:

    你的类方法正在为find_or_initialize_by辅助方法哭泣:

    self.get_event_record(row, participant)
      find_or_initialize_by_participant_id_and_event_type_code_and_event_start_date(:participant_id => participant.id, :event_type_code => row[:event_type_code], :event_start_date => row[:event_start_date].to_friendly_formatted_date)
    end
    

By god it's long, but it achieves what you're trying to do more elegantly (although I'm open to argument!)

通过上帝很长,但它实现了你想要更优雅地做的事情(虽然我愿意参与争论!)

#1


23  

Short answer is no, you cannot use instance methods of a class inside a class method unless you have something like:

简短的回答是否定的,你不能在类方法中使用类的实例方法,除非你有类似的东西:

class A
  def instance_method
    # do stuff
  end

  def self.class_method
     a = A.new
     a.instance_method
  end
end

But as far as I can see, format_date does not have to be an instance method. So write format_date like

但据我所知,format_date不一定是实例方法。所以写format_date就好

def self.format_date(date)
   # do stuff
end

#2


4  

Just create class method

只需创建类方法

def self.format_date (..)
  ...
end

And if u need instance method, delegate it to class method

如果你需要实例方法,请将它委托给类方法

def format_date *args
  self.class.format_date *args
end

And i don't think that it is good idea to call instance methods from class scope

我不认为从类范围调用实例方法是个好主意

#3


3  

You could do YourClassName.new.format_date(your_date), although I think it's pretty clear you should be restructuring your code - this method probably doesn't belong on an instance. Why don't you extend the Date Class, or make format_date a class method on the class you are using?

你可以做YourClassName.new.format_date(your_date),虽然我认为很明显你应该重构你的代码 - 这个方法可能不属于实例。为什么不扩展Date类,或者将format_date作为您正在使用的类的类方法?

EDIT: Here are a few other things to think about with your code:

编辑:以下是您需要考虑的其他一些事项:

  • Your whole format_date method goes to a lot of lengths to manipulate dates as strings. Why not use Ruby's Date Class? Using Date.parse or Date.strptime or even "01/01/2001".to_date might be useful depending on your locale
  • 你的整个format_date方法花了很多篇幅来操作日期作为字符串。为什么不使用Ruby的Date类?使用Date.parse或Date.strptime甚至“01/01/2001”.to_date可能很有用,具体取决于您的语言环境
  • Consider extending the String class for your method, if you really need to make your own method:

    如果您确实需要创建自己的方法,请考虑为您的方法扩展String类:

    class String
      def to_friendly_formatted_date
        Date.strptime(self, "%d/%m/%y")
      end
    end
    "01/08/09".to_friendly_formated_date
    
  • Your class method is crying our for the find_or_initialize_by helper methods:

    你的类方法正在为find_or_initialize_by辅助方法哭泣:

    self.get_event_record(row, participant)
      find_or_initialize_by_participant_id_and_event_type_code_and_event_start_date(:participant_id => participant.id, :event_type_code => row[:event_type_code], :event_start_date => row[:event_start_date].to_friendly_formatted_date)
    end
    

By god it's long, but it achieves what you're trying to do more elegantly (although I'm open to argument!)

通过上帝很长,但它实现了你想要更优雅地做的事情(虽然我愿意参与争论!)