Ruby on Rails 3 - Перезагрузить каталог lib для каждого запроса - PullRequest
58 голосов
/ 19 июля 2010

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

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

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

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

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

Ответы [ 11 ]

49 голосов
/ 06 декабря 2010

Я не смог заставить что-либо из вышеперечисленного работать на меня, поэтому немного покопался в коде 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

  # For Rails 5.1+
  ActiveSupport::Reloader.to_prepare do
    lib_reloader.execute_if_updated
  end

  # For Rails pre-5.1 
  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!

33 голосов
/ 18 мая 2013

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 когда сделано. Мы можем сделать лучше, верно?


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

  • Рельсы 3.0.20
  • Рельсы 3.1.12
  • Рельсы 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. Иначе тебя укусят!

require "beer_creator" unless Rails.env.development?

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

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

21 голосов
/ 25 июля 2011

Поскольку мы говорим о Rails, самый простой способ - «потребовать» ваши файлы lib / * .rb, используя « require_dependency ». Пока контроллер / помощник / etc (файлы .rb в app /) использует require_dependency, а не просто требует перезагрузки, без необходимости делать что-то напуганное.

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

13 голосов
/ 16 сентября 2010

Вы должны добавить

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

в ваш класс Application в config / application.rb

https://rails.lighthouseapp.com/projects/8994/tickets/5218-rails-3-rc-does-not-autoload-from-lib

3 голосов
/ 27 сентября 2012

Вот моя версия, вдохновленная ответом @ pbhogan , который перезагружает все файлы ruby ​​в вашем каталоге 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
3 голосов
/ 20 июля 2010

В 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')

/ Библиотека / 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
1 голос
/ 28 октября 2013

Добавить к 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

Сработало для меня.

1 голос
/ 20 сентября 2012

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

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

Старый ответ

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

Начиная с 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 без его кеширования ...? Я не знаю, как это происходит.)

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

Вот некоторые ресурсы, которые я считаю полезными:

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

0 голосов
/ 26 июня 2013

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

require_dependency 'the_class'

И

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

0 голосов
/ 28 октября 2011

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

#Dir.glob("./lib/*.{rb}").each { |file| require file } # require each file from lib directory
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...