2009-05-09 6 views
16

La méthode Rails Array#to_sentence permet de ce qui suit:méthodes Rails Redéfinir

['a', 'b', 'c'].to_sentence # gives: "a, b, and c" 

Je voudrais étendre cette méthode pour lui permettre de prendre un bloc, de sorte que vous pouvez faire quelque chose comme ce qui suit (où les gens est un tableau d'objets personne, qui ont l'attribut name):

people.to_sentence { |person| person.name } 
# => "Bill, John, and Mark" 

Je n'ai pas de problème avec l'écriture de la méthode d'extension. Mais je ne peux pas savoir où le mettre. Les extensions de base de Rails sont chargées quelque part dans les profondeurs de ActiveSupport. Mon besoin est pour un endroit où le code défini par l'utilisateur est toujours chargé, et est préchargé (avant tout code d'application).

Répondre

23

Créer config/initializers/super_to_sentence.rb. Tous les fichiers de ce répertoire sont chargés après le chargement des Rails. Vous aurez donc la possibilité de remplacer la définition de Rails, soit Array#to_sentence.

Pour le code que vous souhaitez charger avant le chargement de Rails, ajoutez-le à config/environment.rb.

+0

comme cela a été mentionné, ajoutez toutes vos extensions personnalisées à un fichier config/initializers/*. Rb – cpjolicoeur

+0

Merci. Je vais vérifier. – dcw

14

J'aime le faire:

# config/initializers/app.rb 
Dir[File.join(Rails.root, "lib", "core_ext", "*.rb")].each {|l| require l } 

# lib/core_ext/array.rb 
class Array 
    def to_sentence_with_block(*args, &block) 
    if block_given? 
     # do something... 
     # to_sentence_without_block(*args) perhaps? 
    else 
     to_sentence_without_block(*args) 
    end 
    end 
    alias_method_chain :to_sentence, :block 
end 
+0

Merci. btw, je pense que c'est une bonne pratique de se souvenir de la précédente, c'est-à-dire d'ajouter un "alias old_to_sentence to_sentence" avant le defn de la nouvelle méthode et son aliasing. – dcw

14

Je pense que c'est une idée laid. Pourquoi ne pas vous venez d'écrire

people.collect { |person| person.name }.to_sentence 

Cela ressemble presque le même et ne sera pas confondre d'autres personnes qui lisent votre code (comme vous en 2 ans)

+2

Et maintenant, il devient encore plus court: 'people.map (&: name) .to_sentence' – sawa

1

simplement la recherche sur le web, semble comme une bonne pratique est d'ajouter dans lib/

donc si vous voulez étendre une classe rubis (dans mon cas, DateTime), il suffit de mettre le code dans .rb puis dans config/environment.rb:

config.after_initialize do 
    require "lib/super_datetime.rb" 
    end 

mon super_datetime.rb ressemble à ceci (le code de http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/140184):

class DateTime 
    def days_in_month 
    self::class.civil(year, month, -1).day 
    end 
    alias dim days_in_month 
    def weekdays 
    (1..dim).to_a 
    end 
end 

redémarrer votre serveur et vous aurez accès à la nouvelle méthode pour tous les objets DateTime.

Questions connexes