2012-06-28 13 views
9

ich eine Klasse, die diese Klasse Methode enthält:Ruby: Kann ich Instanzmethoden innerhalb einer Klassenmethode verwenden?

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 

Und ich habe auch in der gleichen Klasse, eine Instanzmethode:

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 

Ich erhalte eine ‚nicht definierte Methode‘ Fehler für #format_date. (Ich habe es ohne die self vorne zuerst versucht). Können Sie keine Instanzmethoden in Klassenmethoden derselben Klasse verwenden?

+2

Warum ist 'format_date' eine Instanz-Methode? Es verwendet nichts von der Instanz. – tdgs

+0

Natürlich können Sie nicht. Um eine Instanzmethode aufzurufen, benötigen Sie eine Instanz Ihrer Klasse. –

+0

@tdgs Guter Punkt. Ich habe es zu einer Instanzmethode gemacht, weil ich dachte, dass es eine Klassenmethode wäre, würde bedeuten, dass es öffentlich genutzt wurde, wenn der Fall nur für den internen Gebrauch ist. –

Antwort

22

Kurze Antwort ist nicht zu nennen, können Sie keine Instanz Methoden einer Klasse innerhalb einer Klassenmethode unles verwenden s Sie haben so etwas wie:

class A 
    def instance_method 
    # do stuff 
    end 

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

Aber soweit ich sehen kann, format_date keine Instanzmethode sein muss. So Schreib format_date wie

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

Ich habe eine Instanzmethode, weil von einer Validierung aufgerufen wird, und eine Klassenmethode, die in Ordnung war, um die Instanzmethode aufrufen zu können, um DRY zu sein –

+0

Dann machen Sie so etwas wie Klasse A; def instance_method; self.class.class_method; Ende; def self.class_method; -- Sachen machen -- ; Ende; Ende – tdgs

3

Sie könnten YourClassName.new.format_date(your_date) tun, obwohl ich denke, es ist ziemlich klar, dass Sie Ihren Code restrukturieren sollten - diese Methode gehört wahrscheinlich nicht zu einer Instanz. Warum erweitern Sie nicht die Date-Klasse oder machen Sie format_date eine Klassenmethode für die von Ihnen verwendete Klasse?

EDIT: Hier sind ein paar andere Dinge, die Sie mit Ihrem Code zu denken:

  • Ihre ganze format_date Methode geht auf viele Längen Daten als Zeichenketten zu manipulieren. Warum nicht die Date-Klasse von Ruby verwenden? Mit Date.parse oder Date.strptime oder sogar "01/01/2001".to_date könnte nützlich sein, abhängig von Ihrem Standort
  • Betrachten Sie die String-Klasse für Ihre Methode erstreckt, wenn Sie wirklich Ihre eigene Methode vornehmen müssen:

    class String 
        def to_friendly_formatted_date 
        Date.strptime(self, "%d/%m/%y") 
        end 
    end 
    "01/08/09".to_friendly_formated_date 
    
  • Ihre Klassenmethode weint unsere für die find_or_initialize_by Hilfsmethoden:

    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 
    

von Gott ist es lang, aber es erreicht, was Sie mehr zu tun, elegant sind versucht, (obwohl ich Argument offen bin!)

+0

Ich hatte es ursprünglich als eine Klassenmethode, aber ich dachte (möglicherweise fälschlicherweise), dass Klassenmethoden außerhalb der Klasse verwendet werden sollen, während diese Methode streng eine interne Methode ist. –

+0

Ich denke dieser Gedanke * war * fehlerhaft! Instanzmethoden sollten sich auf die spezifischen Attribute einer Instanz dieser Klasse beziehen. Deine Methode hat wirklich nichts mit einer Instanz zu tun. Ich würde es wieder in eine Klassenmethode verwandeln. Sie haben auch einige Möglichkeiten, Ihren Code neu zu faktorisieren - ich bearbeite meine Antwort. –

+0

@steve_gallagher: Sie können Klassenmethoden privat machen. Sehen Sie sich [this] (https://gist.github.com/3011405) an. – Linuxios

4

Nur Klassenmethode

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

erstellen Und wenn u Instanzmethode benötigen, delegieren sie an Klassenmethode

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

Und ich glaube nicht, dass es eine gute Idee ist, Instanz-Methoden von Klassenbereich

+1

'class.format_args'? Warum rufst du eine Klassenmethode auf der Jewyword 'Klasse'? – Linuxios

+0

weil format_date die Klassenmethode ist –

+2

Das bedeutet nicht, dass das Aufrufen des Schlüsselworts 'class' nichts anderes als einen Syntaxfehler verursacht. Du brauchst "Selbst". – Linuxios

Verwandte Themen