Подтвердить что ты не робот

Ruby on Rails 3 - Перезагрузка каталога lib для каждого запроса

Я создаю новый движок для приложения rails 3. Как вы можете догадаться, этот движок находится в каталоге lib моего приложения.

Однако у меня есть некоторые проблемы, связанные с его развитием. Действительно, мне нужно перезапустить свой сервер каждый раз, когда я что-то меняю в движке.

Есть ли способ избежать этого?

Могу ли я заставить рельсы полностью перезагрузить каталог lib или конкретный файл и его требования для каждого запроса?

Спасибо за вашу помощь:)

4b9b3361

Ответ 1

TL; DR

  • поместите это в config/application.rb

    config.eager_load_paths += ["#{Rails.root}/lib"]

  • удалить инструкции require для ваших файлов lib

Go!


Позвольте мне подробно объяснить.

Я не знаю, почему этот ответ принят, поскольку он не помогает с перезагрузкой папки lib по каждому запросу. Сначала я подумал, что он работает для Rails 2, но в этом вопросе четко сказано, что он был для Rails 3, а дата релиза 3.0.0 - до даты ответа.

Другие ответы кажутся чрезмерно сложными или не обеспечивают реального решения.

Я решил немного разобраться, потому что это беспокоило меня, и я даже обнаружил, что у людей есть обходное решение для этого, и это связано с сохранением файлов lib внутри app/models в разработке, а затем перемещение на /lib когда сделано. Мы можем сделать лучше, верно?


Мое решение проверено на:

  • Rails 3.0.20
  • Rails 3.1.12
  • Rails 3.2.13
  • Rails 4.0.0.rc1

Поместите это в свой config/application.rb:

# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib}"]

Что это! ™

Убедитесь, что вы положили его здесь, так как он не работает, если вы поместите его в config/environments/development.rb, например.

Убедитесь, что вы удалили все операторы require для вашего кода /lib, так как инструкции require также заставят это решение не работать.


Этот код неявно требует вашего кода, поэтому, если вы выполняете проверки среды (что необязательно), и вместо указанного выше кода вы решили написать что-то вроде этого:

# in config/application.rb
config.eager_load_paths += ["#{Rails.root}/lib"] if Rails.env.development?

вы должны следить за старыми операторами require, поскольку они все еще требуются во всех средах без разработки, в этом сценарии.

Итак, если вы все еще решите выполнить проверки среды, убедитесь, что вы выполняете обратные проверки для операторов запроса. В противном случае вас укусят!

require "beer_creator" unless Rails.env.development?

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

Если вы хотите узнать больше об этой теме, посмотрите этот небольшой учебник.

Ответ 2

Я не мог заставить любой из вышеперечисленных работать для меня, поэтому я немного выкопал код Rails и придумал следующее:

Новый файл: config/initializers/reload_lib.rb

if Rails.env == "development"
  lib_reloader = ActiveSupport::FileUpdateChecker.new(Dir["lib/**/*"]) do
    Rails.application.reload_routes! # or do something better here
  end

  ActionDispatch::Callbacks.to_prepare do
    lib_reloader.execute_if_updated
  end
end

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

В основном, это то, что он проверяет, изменились ли какие-либо файлы в /lib (измененная метка времени) с момента последней загрузки, а затем вызывает перезагрузку, если они меняются.

Я мог бы также упомянуть, что у меня это в моем config/application.rb

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

Что только по умолчанию гарантирует, что все в моем каталоге lib загрузится.

Yays!

Ответ 3

Поскольку мы говорим о Rails, самый простой способ - "потребовать" ваши файлы lib/*.rb, используя " require_dependency". До тех пор, пока файлы controller/helper/etc (.rb в приложении /) используют require_dependency, а не просто требуют перезагрузки, без необходимости делать что-либо напуганное.

Прежде чем я пошел по этому треку, единственным решением, которое работало, было то, что было на hemju.com, но я действительно не хотел, чтобы для взлома скорости ApplicationController для Dev.

Ответ 5

В RAILS 3 здесь секретный соус для автоматической перезагрузки файлов lib. Код ниже немного перебор, для примера, но это то, что я сделал, чтобы заставить его работать. Вы можете изменить сообщение в YoYo # gogo и увидеть на экране каждую загрузку страницы. Удалите инициализатор, и он останется тем же.

/config/initializers/lib_reload.rb(новый файл)

ActiveSupport::Dependencies.explicitly_unloadable_constants << 'YoYo'
ActiveSupport::Dependencies.autoload_once_paths.delete(File.expand_path(File.dirname(__FILE__))+'/lib')

/lib/yo_yo.rb

class YoYo
  def gogo
    "OH HAI THERE"
  end
end

/приложение/контроллеры/home_controller

require 'yo_yo'
class HomeController < ApplicationController
  def index
    @message = YoYo.new.gogo
  end
end

Ответ 6

Вот моя версия, вдохновленная ответом @pbhogan, который перезагружает все рубиновые файлы в вашем каталоге rails/lib при изменении любого из этих файлов.

Он также отключает предупреждения, чтобы избежать сообщений относительно уже инициализированных констант.

Работает с Rails 3.2.8

if Rails.env.development?

  lib_ruby_files = Dir.glob(File.join("lib/**", "*.rb"))
  lib_reloader ||= ActiveSupport::FileUpdateChecker.new(lib_ruby_files) do
    lib_ruby_files.each do |lib_file|
      silence_warnings { require_dependency(lib_file) }
    end
  end

  ActionDispatch::Callbacks.to_prepare do
    lib_reloader.execute_if_updated
  end

end

Ответ 7

Обновленный ответ

Я подытоживаю все свои выводы в своем блоге, вы можете посмотреть там:

Старый ответ

Я искал решение для этого тоже, и (для полноты, а также для указания других в этом направлении) вот что я нашел.

С Rails3.1 двигатели могут быть легко сгенерированы с помощью команды rails plugin new my_plugin --full. Это создает скелет для двигателя.

--full означает, что движок будет "слит" прямо во включенное приложение, так что, например, контроллеры должны быть доступны напрямую, как если бы они были определены в приложении, включенном в приложение. Это позволяет вам, например, иметь вспомогательный файл в my_engine/app/helpers/my_helper.rb, который будет объединен прямо в ваше приложение app/helpers/my_helper.rb helper.

Есть еще одна опция --mountable, которая создает пространство имен для движка, чтобы его контроллеры и т.д. никогда не сталкивались с включенными приложениями. Это приводит к, например, хелпер находится в my_engine/app/helpers/my_engine/my_helper.rb, который не столкнется с помощником app/helpers/my_helper.rb в вашем включенном приложении.

Теперь более интересная часть:

В сгенерированной рабочей папке test есть папка dummy, которая содержит полное приложение Rails! Для чего это?

Когда вы разрабатываете движок, его функциональные возможности предназначены для самостоятельной работы, и он также должен быть полностью протестирован сам по себе. Таким образом, это "неправильный" способ разработки движка "внутри" другого приложения Rails (хотя он интуитивно часто будет чувствовать себя правильно при извлечении существующих функций из приложения Rails в движок), и поэтому теоретически также не нужно перезагружать движок кода с каждым запросом к включенному приложению.

"Правильный" способ, похоже, таков: разработать и протестировать ваш движок, как если бы это было полное приложение Rails с помощью приложения dummy! В этом вы можете сделать все, что вы можете сделать в любом "обычном" Rails-приложении, например. создавать контроллеры, модели, представления и т.д., которые используют функциональные возможности, которые должен обеспечить движок. Обычно вы можете запускать сервер с помощью rails s в каталоге test/dummy и обращаться к фиктивному приложению на localhost:3000, а при выполнении тестов приложение dummy автоматически используется для тестов интеграции. Довольно мило!: -)

Вы должны быть осторожны, где разместить свои вещи:

  • Любая функциональность, предназначенная для использования в другом приложении Rails, переходит в my_engine/app, тогда как любая функция, которая требуется только для проверки функциональности движка, переходит в test/dummy/app.

Затем вы можете легко загрузить свой движок в основное приложение Gemfile следующим образом: gem 'my_engine', :path => 'path/to/my_engine' или опубликовать его в GitHub как драгоценный камень.

(Одна интересная вещь (и вернуться к этой теме) заключается в том, что когда я запускаю фиктивный сервер, все изменения в движке кажутся отраженными внутри него! Итак, как-то кажется возможным включить движок в приложении Rails без кэширования...? Я не знаю, как это происходит.)

Итак, чтобы подвести итог: двигатель обеспечивает функциональность, которая может полностью стоять сама по себе, поэтому ее также следует разрабатывать и тестировать самостоятельно. Затем, когда он достиг стабильного состояния, он может быть включен любым другим приложением, которое нуждается в его функциональности.

Здесь некоторые ресурсы, которые я нахожу полезными:

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

Ответ 8

Добавьте в application_controller.rb или ваш базовый контроллер:

  before_filter :dev_reload if Rails.env.eql? 'development'

  def dev_reload
    # add lib files here
    ["rest_client.rb"].each do |lib_file|
      ActiveSupport::Dependencies.load_file lib_file
    end
  end

Работал для меня.

Ответ 9

обратите внимание, что в Rails 3 "load_once_paths" становится "autoload_once_paths."

Кроме того, кажется, что он должен быть пустым, если вы явно не помещаете в него что-либо.

Ответ 10

Кроме того, убедитесь, что вы закомментируете следующую строку в application.rb(в дополнение к решению @dishod) и убедитесь, что имя вашего модуля совпадает с именем вашего файла (иначе рельсы не смогут чтобы найти его)

#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory

Ответ 11

Работает для Rails 3.2.13 для перезагрузки lib внутри gem приложения:

require_dependency 'the_class'

и

config.autoload_paths + =% W (# {config.root}/../fantasy/lib)