17

As I understand it, plugins are not reloaded in Rails with each request in development mode. Which makes sense, as generally you add plugins to your app and it's the app you're developing.

But if you are developing a plugin, you have to restart the server with each change to the plugin which has a significant overhead.

Is there any way to make Rails reload your plugin during development, the way it reloads your models and controllers?

user229044
  • 232,980
  • 40
  • 330
  • 338
msaspence
  • 1,424
  • 2
  • 14
  • 25

6 Answers6

10

I have been struggling with this for some time, too. None of the solutions work, including the autoload_paths and autoload_once_paths tricks. Furthermore, the hack with FileUpdateChecker and initializers also does not help (the checker triggers properly, but the files are not reloaded). Same for config.reload_plugins = true...

However, there is a solution. In app/controllers/application_controller.rb add one line: require_dependency 'your_file_name_here' The application controller is reloaded on every request and require_dependency makes your file to be checked for modifications and reloaded accordingly. It worked for me, Apache 2, Passenger 3 and Rails 3.0.3.

tokland
  • 66,169
  • 13
  • 144
  • 170
Miki
  • 7,052
  • 2
  • 29
  • 39
  • On a second pass, config.reload_plugins = true is working for me. – drewrobb Apr 05 '11 at 21:11
  • require_dependency worked for me. In addition, as my plugin requires its own files in turn, I had to replace those require statements with require_dependency... – Peter Ehrlich Dec 13 '11 at 22:40
  • I suspect reload_plugins didn't work because presumably I have the files set up wrong, and they don't get loaded by rails automatically, requiring instead a manual 'require' statement. http://stackoverflow.com/questions/1073076/rails-lib-modules-and – Peter Ehrlich Dec 13 '11 at 22:42
  • In `application.rb` instead than on controller: `ActionDispatch::Reloader.to_prepare{ require_dependency 'your_file' }` – brauliobo Dec 16 '15 at 13:47
  • I only got this to work when _also_ adding the lib-dir to autoload paths. That is: in `test/dummy/config/application.rb` inside the `class Application < Rails::Application do`-block add: `config.autoload_paths += %W{ #{Rails.root.join('../../lib/')} }` – Andreas Storvik Strauman Jul 31 '18 at 12:25
3

I do this by using the shotgun gem.

gem install shotgun

cd /path/to/rails/app

shotgun

slower response time, but reloading all the rails code, not wasting time to write autoload_paths

2

Easy way, develop your plugin in a folder inside the "app" folder:

  • app
    • models
    • controllers
    • helpers
    • views
    • your_plugin_here

This way, all your plugin classes will be reloaded on each request.

Another possibility is to add the path at your application.rb file:

require File.expand_path('../boot', __FILE__)
require 'rails/all'
Bundler.require(:default, Rails.env) if defined?(Bundler)

module SunspotTutorial
  class Application < Rails::Application

    config.autoload_paths += %W{ #{config.root}/plugins/your_plugin_name/lib }

    #lots of other code
  end
end

This way your plugin is going to be reloaded all the time.

Maurício Linhares
  • 39,901
  • 14
  • 121
  • 158
  • thats what I've resorted to but it doesn't seem like the best solution – msaspence Jan 17 '11 at 12:34
  • what kind of solution do you want? – Joshua Partogi Jan 17 '11 at 13:15
  • If a way that doesn't ask you to configure anything and just works is not te best solution, i'm out of ideas. – Maurício Linhares Jan 17 '11 at 13:28
  • are you saying that i can just move my plugin directory from vendor/plugins to under /app and it will just work? – msaspence Jan 17 '11 at 13:44
  • Not your plugin directory, whatever you'd put inside your plugin's lib folder should be placed into "app/your_plugin_folder" and everything will be reloaded. Once you're done with coding your plugin, move it to the right folder (or just keep it inside app anyway if you don't plan to release it to the public). – Maurício Linhares Jan 17 '11 at 13:52
  • what about when I want to develop a new feature I have to move it back out and then in again whilst it works its not elegant and if I have multiple files i've got to manual keep track of what has changed simply being able to tell rails to reload plugins or even everything in development mode would be ideal – msaspence Jan 17 '11 at 13:59
  • The second option seems to work fine. I would recommend to put this "config.autoload_paths += %W{ #{config.root}/plugins }" into development config file (not application config) – Marcin Jul 13 '22 at 20:30
1

If restarting the server automatically when plugin code changes is an acceptable solution, you could use Mike Clark/topfunky's rstakeout for that, or the newer watchr which sounds like it does the same thing.

You would do something like this:

rstakeout 'touch tmp/restart.txt' 'vendor/plugins/**/*'
Zubin
  • 9,422
  • 7
  • 48
  • 52
  • 1
    Guard is also a good solution to watching files for changes. The guard-passenger plugin restarts the server when files change: https://github.com/mordaroso/guard-passenger – Kris May 26 '11 at 17:12
0

With https://github.com/ranmocy/guard-rails, it's super easy:

# Gemfile.local
gem 'guard-rails'


$ bundle
$ guard init rails


# Guardfile:
guard 'rails' do
  watch('Gemfile.lock')
  watch(%r{^(config|plugins)/.*})
end


$ bundle exec guard
Marek Příhoda
  • 11,108
  • 3
  • 39
  • 53
0

This solution, for engines, works on Rails 2.3 but comes with one cavaet, it will load all files in the engine and parent app on every request which will make response times slower.

# lib/my_engine/engine.rb
if ENV['RELOAD_MYENGINE'] && Rails.env.development?
  config.to_prepare do
    Rails.logger.debug "RELOADING MY ENGINE"
    require_dependency MyEngine::Engine.root.join('lib', 'my_engine').to_s
  end

config.after_initialize do
  Rails.application.config.reload_classes_only_on_change = false
end

Then start the server:

RELOAD_MYENGINE=1 rails server
Kris
  • 19,188
  • 9
  • 91
  • 111