10

Quelle est la méthode recommandée pour étendre le comportement des classes, via class_eval et les modules (pas par héritage) si je veux étendre une classe enfouie dans un Gem à partir d'une application Rails 3?Comment/Quand/Où étendre les classes de gemmes (via class_eval et Modules) dans Rails 3?

Un exemple est la suivante:

Je veux ajouter la possibilité de créer des permaliens pour les balises et les catégories (par les pierres précieuses ActsAsTaggableOn et ActsAsCategory). Ils ont défini les modèles Tag et Category.

Je veux faire essentiellement ceci:

Category.class_eval do 
    has_friendly_id :title 
end 

Tag.class_eval do 
    has_friendly_id :title 
end 

Même s'il y a d'autres façons d'ajouter cette fonctionnalité qui pourrait être spécifique à la pierre précieuse, ce qui est la méthode recommandée pour ajouter un comportement à des classes dans Rails 3 application comme ça?

J'ai quelques autres gemmes que j'ai créées que je veux faire ceci, comme un modèle Configuration et un modèle Asset. Je voudrais être en mesure d'ajouter créer une classe de modèle app/models/configuration.rb à mon application, et il agirait comme si je viens de le faire class_eval.

De toute façon, comment cela est-il supposé fonctionner? Je ne trouve rien qui couvre cela de l'un des blogs/docs/gists courants Rails 3.

Répondre

9

Je le fais comme suit, ajoutez d'abord un fichier config/initializers où vous pouvez exiger que les fichiers qui contiennent vos extensions:

# config/initializers/extensions.rb 
require "#{Rails.root}/app/models/category.rb" 
require "#{Rails.root}/app/models/tag.rb" 

Ensuite, vous pouvez simplement rouvrir les classes et ajouter tout ce que vous besoin:

# app/models/category.rb 
class Category 
    has_friendly_id :title 
end 

Seul inconvénient est que le serveur doit être redémarré pour que toute modification de ces fichiers prennent effet, pas sûr s'il y a une meilleure façon qui permettrait de surmonter cela.

+0

J'ai le même problème, je reçois 'LoadError: attendu app/models/tag.rb pour définir Tag' – MhdSyrwan

+0

MhdSyrwan: Cela signifie que dans votre fichier 'tag.rb', la première classe à définir doit être appelée exactement "Tag", donc il semble que vous ne l'avez pas nommé de la bonne façon. –

0

Vous pouvez utiliser rails_engine_decorator bijou: https://github.com/atd/rails_engine_decorators

il suffit d'ajouter dans votre Gemfile:

gem 'rails_engine_decorator' 

Et utilisateur class_eval dans vos décorateurs:

/app/decorators/models/category_decorator.rb 
/app/decorators/models/tag_decorator.rb 

Il fonctionne pour moi. J'espère que tu trouves cela utile!