Comment créer un générateur qui modifie un fichier. Je cherche à faire en sorte qu'il trouve un motif dans un fichier et ajoute le contenu de la ligne en dessous.Modifier un fichier avec un générateur de rails
Répondre
Rails générateur de l'échafaudage fait quand il ajoute une route vers config/routes.rb
Elle le fait en appelant une méthode très simple:
def gsub_file(relative_destination, regexp, *args, &block)
path = destination_path(relative_destination)
content = File.read(path).gsub(regexp, *args, &block)
File.open(path, 'wb') { |file| file.write(content) }
end
Qu'est-ce qu'il fait est de prendre un chemin/fichier comme premier argument, suivi par un motif regexp, des arguments gsub et le bloc. C'est une méthode protégée que vous devrez recréer pour pouvoir l'utiliser. Je ne sais pas si vous aurez accès à destination_path
, alors vous voudrez probablement passer le chemin exact et ignorer toute conversion.
Pour utiliser gsub_file
, disons que vous souhaitez ajouter des balises à votre modèle utilisateur. Voici comment vous le faire:
line = "class User < ActiveRecord::Base"
gsub_file 'app/models/user.rb', /(#{Regexp.escape(line)})/mi do |match|
"#{match}\n has_many :tags\n"
end
vous trouvez la ligne spécifique dans le fichier, l'ouvreur de classe, et en ajoutant votre has_many
ligne droite au-dessous. Mais attention, parce que c'est le moyen le plus fragile d'ajouter du contenu, c'est pourquoi le routage est l'un des seuls endroits qui l'utilise. L'exemple ci-dessus serait normalement géré avec un mix-in.
J'aime la réponse de Jaime. Mais, quand j'ai commencé à l'utiliser, j'ai réalisé que j'avais besoin de faire quelques modifications. Voici l'exemple de code J'utilise:
private
def destination_path(path)
File.join(destination_root, path)
end
def sub_file(relative_file, search_text, replace_text)
path = destination_path(relative_file)
file_content = File.read(path)
unless file_content.include? replace_text
content = file_content.sub(/(#{Regexp.escape(search_text)})/mi, replace_text)
File.open(path, 'wb') { |file| file.write(content) }
end
end
En premier lieu, gsub
remplacera toutes les instances du texte de recherche; J'ai seulement besoin d'un. J'ai donc utilisé sub
à la place.
Ensuite, j'ai dû vérifier si la chaîne de remplacement était déjà en place. Sinon, je répéterais l'insertion si mon générateur de rails a été exécuté plusieurs fois. J'ai donc enveloppé le code dans un bloc unless
. J'ai enfin ajouté le def destination_path()
pour vous.
Maintenant, comment l'utiliseriez-vous dans un générateur de rails? Voici un exemple de la façon dont je fais simplecov vous est installé pour rspec et concombre:
def configure_simplecov
code = "#Simple Coverage\nrequire 'simplecov'\nSimpleCov.start"
sub_file 'spec/spec_helper.rb', search = "ENV[\"RAILS_ENV\"] ||= 'test'", "#{search}\n\n#{code}\n"
sub_file 'features/support/env.rb', search = "require 'cucumber/rails'", "#{search}\n\n#{code}\n"
end
Il y a probablement une façon plus élégante et DRY-er pour le faire. J'ai vraiment aimé comment ajouter un bloc de texte à l'exemple de Jamie. J'espère que mon exemple ajoute un peu plus de fonctionnalité et de vérification d'erreurs.