2009-05-12 2 views
1

, par tous les assistants, à travers toute ma application Rails, remplacez cette syntaxe:Comment puis-je faire rails aides plus je voudrais orienté objet

time_ago_in_words(@from_time) 

avec ceci:

@from_time.time_ago_in_words 

Idéalement, ce changement rendrait également les aides disponibles n'importe où dans mon application (de la même manière, par exemple, 5.times est).

Est-ce que quelqu'un sait d'un plugin qui fait cela? Serait-il difficile de rouler le mien?

+0

Pourquoi est-ce important? Peut-être que le contexte aiderait ... – runako

+0

Je trouve juste leur syntaxe existante agaçante et laide. Il serait aussi bien d'appeler des choses comme @ post.truncate dans mon modèle (pour la mise en cache, par exemple) –

Répondre

4

Si vous créez un nouveau modèle, vous pouvez le faire hériter des méthodes d'une classe existante.

Exemple (app/modèles/mykindofstring.rb):

class Mykindofstring < String 

    def all_caps_and_reverse 
     self.upcase.reverse 
    end 

end 

Ensuite, à partir du contrôleur:

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

et enfin l'appeler de la vue:

<%= @my_string %> 

affiche comme Ceci est ma chaîne, tandis que:

<%= @my_string.all_caps_and_reverse %> 

affiche comme GNIRTS YM SI SIHT.

La classe hérite de la classe de chaînes, donc toutes les méthodes qui s'appliquent à une chaîne s'appliquent également à un objet mykindofstring. La méthode qui s'y trouve est juste un nouveau nom pour une combinaison de deux méthodes de chaînes existantes, mais vous pouvez le faire faire ce que vous voulez, comme une méthode pour convertir un temps en une chaîne formatée. Fondamentalement, il s'agit juste d'étendre une classe Ruby actuelle avec vos propres méthodes au lieu d'utiliser les fonctions/helpers.

Major Modifier

Sur la base de commentaires Ians à cette réponse et sa propre réponse à la question ci-dessus, j'ai joué un peu dans Rails et est venu avec l'ajout de ce à application_helper.rb:

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

maintenant, il suffit d'appeler la méthode sur une chaîne dans l'application:

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

.gnirts un si siht

+0

Mais c'est Ruby! Le sous-classement est "correct" OO, mais vous ne voulez pas créer de nouveaux objets d'un autre type, vous voulez utiliser des chaînes réelles données par Dieu, donc ouvrez simplement la classe String et ajoutez votre méthode: class String; def all_caps_and_reverse; self.upcase.reverse; fin; fin –

+0

Merci, bon point. J'ai révisé la réponse en conséquence. Btw, c'est pourquoi j'aime Stack Overflow; Je ne suis ici que depuis quelques jours et mon code s'améliore déjà. – Jarrod

+0

Pourquoi le faire avec class_eval plutôt que de simplement redéclarer la classe de chaînes? –

0

Faire un modèle, TimeAgo ou quelque chose de similaire. Mettre en œuvre suivant cette idée ici: a code snippet for "wordifying" numbers

Ensuite, dans votre contrôleur, créez les variables d'instance en utilisant cette classe. Ensuite, à votre avis, appelez @from_time.in_words

1

Vous ne trouverez aucun moyen facile de faire cela sur l'ensemble de votre application pour tous (voire la plupart) des assistants.

Les aides sont structurés en modules destinés à être inclus dans les classes de rendu des vues.Pour les exploiter, vous devez garder une copie d'un ActionView autour (pas une affaire énorme, je suppose).

Vous pouvez toujours ouvrir les classes et spécifier chaque aide que vous voulez, si:

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" 

Si vous prenez cette approche, je recommande la mise en cache de l'instance ActionView :: Base que vous utilisez. Ou, si vous ne voulez pas aller trop lourd, vous pouvez créer votre propre classe pour inclure les assistants que vous voulez (vous ne voulez pas inclure les assistants directement dans chaque classe Time, Date, String, etc. , car cela va encombrer l'espace de noms de la méthode assez féroce - et entrer en conflit avec les noms naturels que vous voulez).

1

Si vous utilisez Ruby 2.1, vous pouvez utiliser Refinements. Ils sont une alternative aux classes de Ruby. à emprunter @Jarrod's monkey-patch exemple:

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

Vous pouvez maintenant utiliser dans un objet que vous voulez:

class Post 
    using MyString 
end 
@post.title.all_caps_and_reverse 

Vous pouvez read more about Refinements ici.

Questions connexes