Изменить файл с помощью генератора рельсов - PullRequest
12 голосов
/ 18 января 2010

Как создать генератор, который изменяет файл.

Я пытаюсь сделать так, чтобы он нашел шаблон в файле и добавил содержимое строки в строку под ним.

Ответы [ 2 ]

16 голосов
/ 19 января 2010

Генератор скаффолдов Rails делает это, когда добавляет маршрут к config/routes.rb Он делает это, вызывая очень простой метод:

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

В качестве первого аргумента он принимает путь / файл, за которым следуют шаблон регулярного выражения, аргументы gsub и блок. Это защищенный метод, который вы должны будете воссоздать, чтобы использовать. Я не уверен, что destination_path - это то, к чему у вас есть доступ, поэтому вы, вероятно, захотите указать точный путь и пропустить любое преобразование.

Чтобы использовать gsub_file, допустим, вы хотите добавить теги к своей модели пользователя. Вот как бы вы это сделали:

line = "class User < ActiveRecord::Base"
gsub_file 'app/models/user.rb', /(#{Regexp.escape(line)})/mi do |match|
  "#{match}\n  has_many :tags\n"
end

Вы находите конкретную строку в файле, средство открытия классов и добавляете строку has_many прямо под ней.

Будьте осторожны, потому что это самый хрупкий способ добавления контента, поэтому маршрутизация - это единственное место, где его используют. Приведенный выше пример обычно обрабатывается с помощью дополнения.

1 голос
/ 03 июня 2013

Мне нравится ответ Хайме.Но когда я начал использовать его, я понял, что мне нужно внести некоторые изменения.Вот пример кода, который я использую:

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

Во-первых, gsub заменит ВСЕ экземпляры текста поиска;Мне нужен только один.Поэтому вместо того, чтобы использовать sub.

Далее, мне нужно было проверить, была ли строка замены уже на месте.В противном случае, я бы повторил вставку, если бы мой генератор рельсов запускался несколько раз.Поэтому я завернул код в блок unless.

Наконец, я добавил для вас def destination_path().

Теперь, как бы вы использовали это в генераторе рельсов?Вот пример того, как я должен убедиться, что simplecov установлен для rspec и cucumber:

  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

Вероятно, есть более элегантный и СУХОЙ способ сделать это.Мне очень понравилось, как вы можете добавить блок текста на примере Джейми.Надеюсь, мой пример добавляет немного больше функциональности и проверку ошибок.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...