2012-06-28 1 views
9

У меня есть класс, который содержит этот метод класса:Ruby: Можно ли использовать методы экземпляра внутри метода класса?

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 

И у меня есть, в том же классе, метод экземпляра:

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 

Я получаю «неопределенный метод» ошибка для #format_date. (Сначала я попробовал это без self). Не можете ли вы использовать методы экземпляра в методах класса того же класса?

+2

Почему метод 'format_date' является экземпляром? Он не использует ничего из экземпляра. – tdgs

+0

Конечно, вы не можете. Для вызова метода экземпляра вам нужен экземпляр вашего класса. –

+0

@tdgs Хорошая точка. Я сделал это методом экземпляра, потому что я думал, что создание метода класса подразумевает, что оно предназначено для публичного использования, когда дело касается только внутреннего использования. –

ответ

22

Короткий ответ: нет, вы не можете использовать методы экземпляра класса внутри метода класса unles S у вас есть что-то вроде:

class A 
    def instance_method 
    # do stuff 
    end 

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

Но, насколько я могу видеть, format_date не должны быть методом экземпляра. Так написать format_date как

def self.format_date(date) 
    # do stuff 
end 
+0

У меня есть метод экземпляра, потому что вызывается из проверки и метод класса, который был бы прав, чтобы иметь возможность вызвать метод экземпляра, чтобы быть DRY –

+0

Затем сделайте что-то вроде этого 'class A; def instance_method; self.class.class_method; конец; def self.class_method; - делать вещи -; конец; end' – tdgs

3

Вы можете сделать YourClassName.new.format_date(your_date), хотя я думаю, что довольно ясно, что вы должны перестроить свой код - этот метод, вероятно, не принадлежит экземпляру. Почему бы вам не расширить класс даты или сделать метод format_date классом, который вы используете?

EDIT: Вот несколько других вещей, чтобы думать о том, с кодом:

  • весь Ваш format_date метод идет на много длины, чтобы манипулировать даты как строки. Почему бы не использовать Ruby's Date Class? Использование Date.parse или Date.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 
    

по бога это долго, но это достигает того, что вы пытаетесь сделать более элегантно (хотя я открыт для аргумента!)

+0

Первоначально я использовал его как метод класса, но я думал (возможно, ошибочно), что методы класса предназначены для использования вне класса, в то время как этот метод является строго внутренним методом. –

+0

думаю эта мысль * был * ошибочный! Методы экземпляров должны относиться к конкретным атрибутам экземпляра этого класса. Ваш метод действительно не имеет никакого отношения к экземпляру вообще. Я вернул бы его в классный метод. У вас есть несколько возможностей перефакторировать свой код, я отредактирую свой ответ. –

+0

@steve_gallagher: вы можете использовать методы класса private. Взгляните на [this] (https://gist.github.com/3011405). – Linuxios

4

Просто создайте метод класса

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

А если и нужен метод экземпляра, делегировать его методу класса

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

И я не думаю, что это хорошая идея, чтобы вызвать методы экземпляра из области видимости класса

+1

'class.format_args'? Почему вы вызываете метод класса в классе jeyword? – Linuxios

+0

, потому что format_date - метод класса –

+2

Это не значит, что вызов его по ключевому слову 'class' будет делать что-либо, кроме синтаксической ошибки. Вам нужно 'self'. – Linuxios