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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11245282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 03:36:51  来源:igfitidea点击:

Ruby: Can I use instance methods inside a class method?

ruby-on-railsrubyclass-methodinstance-methods

提问by steve_gallagher

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 selfin front, at first). Can you not use instance methods in class methods of the same class?

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

回答by tdgs

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_datedoes not have to be an instance method. So write format_date like

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

def self.format_date(date)
   # do stuff
end

回答by Yuri Barbashov

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

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

回答by Rob d'Apice

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_datea 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_datemethod goes to a lot of lengths to manipulate dates as strings. Why not use Ruby's Date Class? Using Date.parseor Date.strptimeor even "01/01/2001".to_datemight be useful depending on your locale
  • Consider extending the String class for your method, if you really need to make your own method:

    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_byhelper methods:

    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
    
  • 您的整个format_date方法花费了很多时间来将日期作为字符串进行操作。为什么不使用 Ruby 的 Date 类?根据您的语言环境使用Date.parseDate.strptime什至"01/01/2001".to_date可能有用
  • 如果您确实需要创建自己的方法,请考虑为您的方法扩展 String 类:

    class String
      def to_friendly_formatted_date
        Date.strptime(self, "%d/%m/%y")
      end
    end
    "01/08/09".to_friendly_formated_date
    
  • 您的类方法正在为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!)

天啊,它很长,但它实现了你想要做的更优雅的事情(尽管我愿意争论!)