2009-05-12 10 views
1

Ich mag würde für alle Helfer, über meine gesamte Anwendung Rails, ersetzen Sie diese Syntax:Wie kann ich Schienen Helfer mehr objektorientierte

time_ago_in_words(@from_time) 

mit diesem:

@from_time.time_ago_in_words 

Idealerweise würde diese Änderung die Helfer auch überall in meiner Anwendung verfügbar machen (genauso, sagen wir 5.times).

Kennt jemand ein Plugin, das das tut? Wäre es schwer, meine eigenen zu rollen?

+0

Warum ist das wichtig? Vielleicht würde etwas Kontext helfen ... – runako

+0

Ich finde nur ihre vorhandene Syntax lästig und hässlich. Es wäre auch schön, Dinge wie @ post.truncate in meinem Modell zu nennen (zum Beispiel Caching) –

Antwort

4

Wenn Sie ein neues Modell erstellen, können Sie die Methoden aus einer vorhandenen Klasse erben.

Beispiel (app/Modelle/mykindofstring.rb):

class Mykindofstring < String 

    def all_caps_and_reverse 
     self.upcase.reverse 
    end 

end 

dann von der Steuerung:

@my_string = Mykindofstring.new('This is my string') 

und schließlich aus der Sicht Aufruf:

<%= @my_string %> 

Displays as Dies ist meine Zeichenfolge, während:

<%= @my_string.all_caps_and_reverse %> 

zeigt als GNIRTS YM SI SIHT.

Die Klasse erbt von der String-Klasse, sodass alle Methoden, die auf eine Zeichenfolge angewendet werden, auch für ein mykindofstring-Objekt gelten. Die darin enthaltene Methode ist nur ein neuer Name für eine Kombination aus zwei vorhandenen Zeichenfolgenmethoden. Sie können jedoch festlegen, dass sie das tut, was Sie möchten, z. B. eine Methode zum Konvertieren einer Zeit in eine formatierte Zeichenfolge.

Im Grunde ist es nur eine aktuelle Ruby-Klasse mit Ihren eigenen Methoden statt Funktionen/Helfer erweitern.

Haupt bearbeitet

Basierend auf Ians Kommentar zu dieser Antwort und seine eigenen Antwort auf die obige Frage, spielte ich ein wenig herum in Rails und kam mit dem Hinzufügen dies die application_helper.rb up:

module ApplicationHelper 
    String.class_eval do 
    def all_caps_and_reverse 
     self.upcase.reverse 
    end 
    end 
end 

Nun rufen Sie einfach die Methode auf eine beliebige Zeichenfolge in der App:

@string = 'This is a string.' 
@string.all_caps_and_reverse 

einen si Siht .gnirts

+0

Aber es ist Ruby! Subclassing ist "richtige" OO, aber Sie wollen nicht neue Objekte eines anderen Typs erstellen, Sie wollen tatsächlich von Gott gegebene Strings verwenden, also öffnen Sie einfach die String-Klasse und fügen Sie Ihre Methode hinzu: class String; def all_caps_and_reverse; self.upcase.reverse; Ende; Ende –

+0

Danke, guter Punkt. Ich habe die Antwort entsprechend überarbeitet. Btw, deshalb mag ich Stack Overflow; Ich bin erst seit ein paar Tagen hier und mein Code verbessert sich bereits. – Jarrod

+0

Warum mit class_eval, anstatt nur die String-Klasse neu zu deklarieren? –

0

Machen Sie ein Modell, TimeAgo oder etwas ähnliches. Implementieren Sie diese Idee hier: a code snippet for "wordifying" numbers

Dann erstellen Sie in Ihrer Steuerung die Instanzvariablen mit dieser Klasse. Dann rufen Sie in Ihrer Ansicht @from_time.in_words

1

Sie werden keine einfache Möglichkeit finden, dies in Ihrer gesamten Anwendung für alle (oder auch die meisten) Helfer zu tun.

Hilfsprogramme sind als Module strukturiert, die in Ansichtsklassen zur Darstellung einbezogen werden sollen.Um sie zu nutzen, müßtest du eine Kopie von ActionView herumliegen haben (kein großes Geschäft, nehme ich an).

Sie können jederzeit die Klassen öffnen und geben Sie jeden Helfer Sie wollen, aber:

class Time 
    def time_ago_in_words 
    ActionView::Base.new.time_ago_in_words self 
    end 
end 

>> t = Time.now 
=> Tue May 12 10:54:07 -0400 2009 
>> t.time_ago_in_words 
=> "less than a minute" 
(wait a minute) 
>> t.time_ago_in_words 
=> "1 minute" 

Wenn Sie diesen Ansatz nehmen, empfehle ich die Instanz von ActionView Cachen :: Base, die Sie verwenden. Oder, wenn Sie nicht so schwer werden wollen, können Sie Ihre eigene Klasse erstellen, um nur die Helfer einzubeziehen, die Sie wollen (Sie möchten die Helfer nicht direkt in jede Klasse Time, Date, String usw. einfügen) , da dies den Methodennamespace recht heftig aufwirbelt - und mit den natürlichen Namen, die Sie wollen, in Konflikt steht.

1

Wenn Sie Ruby 2.1 verwenden, können Sie Verfeinerungen verwenden. Sie sind eine Alternative zum Affepatching von Rubys Klassen. @Jarrod's monkey-patch Beispiel zu leihen:

module MyString 
    refine String do 
    def all_caps_and_reverse 
     upcase.reverse 
    end 
    end 
end 

können Sie jetzt das Sie in ein beliebiges Objekt verwenden möchten:

class Post 
    using MyString 
end 
@post.title.all_caps_and_reverse 

können Sie read more about Refinements hier.