Grape: Undefined method 'to_prepare' for ActionDispatch::Callbacks:Class (NoMethodError)

Created on 25 Jul 2017  路  10Comments  路  Source: ruby-grape/grape

Using Rails 5.1.2, Ruby 2.4.0p0

I have an existing app, attempting to add a Grape API on top of it to call it from another app. Following the documentation, I put the following code in app/api/wlp/api.rb:

module WLP
    class API < Grape::API
        version 'v1', using: :header, vendor: 'Washington Listing Pros'
        format :json
        prefix :api

        resource :listings do
            desc 'Return all listings'
            get :listings do
                Listing.all
            end

            desc 'Return a listing'
            params do
                requires :id, type: Integer, desc: 'Listing ID'
            end
            route_param :id do
                get do
                    Listing.find(params[:id])
                end
            end
        end
    end
end

Put the following in my application.rb:

config.paths.add File.join('app', 'api'), glob: File.join('**', '*.rb')
config.autoload_paths += Dir[Rails.root.join('app', 'api', '*')]

My config/routes.rb:

Rails.application.routes.draw do
    mount WLP::API => '/'
    resources :listings, only: [:show, :new, :create, :edit]
    root 'landing#index'
    get 'contact', to: 'contact', controller: 'landing', as: :contact
end

I installed the hashie forbidden attributes gem properly. I created the config/initializers/reload_api.rb file:

if Rails.env.development?
    ActiveSupport::Dependencies.explicitly_unloadable_constants << 'Twitter::API'

    api_files = Dir[Rails.root.join('app', 'api', '**', '*.rb')]
    api_reloader = ActiveSupport::FileUpdateChecker.new(api_files) do
        Rails.application.reload_routes!
    end
    ActionDispatch::Callbacks.to_prepare do
        api_reloader.execute_if_updated
    end
end

I'm receiving the error message when I try to start the Rails server. Is this not supported for 5.1.2?

bug?

Most helpful comment

Rails 5.1 removed ActionDispatch::Callbacks#to_prepare (see https://github.com/rails/rails/commit/3f2b7d60a52ffb2ad2d4fcf889c06b631db1946b); so the issue lies in your reload_api.rb initializer. Replacing it with ActiveSupport::Reloader.to_prepare should fix the issue.

All 10 comments

Call stack?

Sorry, here ya go:

from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.1.2/lib/active_support/dependencies.rb:286:in `load'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.1.2/lib/active_support/dependencies.rb:286:in `block in load'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.1.2/lib/active_support/dependencies.rb:258:in `load_dependency'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.1.2/lib/active_support/dependencies.rb:286:in `load'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/engine.rb:655:in `block in load_config_initializer'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/activesupport-5.1.2/lib/active_support/notifications.rb:168:in `instrument'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/engine.rb:654:in `load_config_initializer'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/engine.rb:612:in `block (2 levels) in <class:Engine>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/engine.rb:611:in `each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/engine.rb:611:in `block in <class:Engine>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:30:in `instance_exec'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:30:in `run'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:59:in `block in run_initializers'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:228:in `block in tsort_each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:350:in `block (2 levels) in each_strongly_connected_component'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:422:in `block (2 levels) in each_strongly_connected_component_from'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:431:in `each_strongly_connected_component_from'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:421:in `block in each_strongly_connected_component_from'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:48:in `each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:48:in `tsort_each_child'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:415:in `call'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:415:in `each_strongly_connected_component_from'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:349:in `block in each_strongly_connected_component'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:347:in `each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:347:in `call'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:347:in `each_strongly_connected_component'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:226:in `tsort_each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/tsort.rb:205:in `tsort_each'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/initializable.rb:58:in `run_initializers'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/application.rb:353:in `initialize!'
    from /home/paul/pmds/websites/listingpros/washingtonlistingpros/config/environment.rb:5:in `<top (required)>'
    from config.ru:3:in `require_relative'
    from config.ru:3:in `block in <main>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/builder.rb:55:in `instance_eval'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/builder.rb:55:in `initialize'
    from config.ru:in `new'
    from config.ru:in `<main>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/builder.rb:49:in `eval'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/builder.rb:49:in `new_from_string'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/builder.rb:40:in `parse_file'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/server.rb:319:in `build_app_and_options_from_config'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/server.rb:219:in `app'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:24:in `app'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/rack-2.0.3/lib/rack/server.rb:354:in `wrapped_app'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:80:in `log_to_stdout'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:42:in `start'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:131:in `block in perform'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:126:in `tap'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands/server/server_command.rb:126:in `perform'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/thor-0.19.4/lib/thor/command.rb:27:in `run'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/thor-0.19.4/lib/thor/invocation.rb:126:in `invoke_command'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/thor-0.19.4/lib/thor.rb:369:in `dispatch'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/command/base.rb:63:in `perform'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/command.rb:44:in `invoke'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/railties-5.1.2/lib/rails/commands.rb:16:in `<top (required)>'
    from /home/paul/pmds/websites/listingpros/washingtonlistingpros/bin/rails:9:in `require'
    from /home/paul/pmds/websites/listingpros/washingtonlistingpros/bin/rails:9:in `<top (required)>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/client/rails.rb:28:in `load'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/client/rails.rb:28:in `call'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/client/command.rb:7:in `call'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/client.rb:30:in `run'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/bin/spring:49:in `<top (required)>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/binstub.rb:31:in `load'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/gems/2.4.0/gems/spring-2.0.2/lib/spring/binstub.rb:31:in `<top (required)>'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:68:in `require'
    from /home/paul/.rbenv/versions/2.4.0/lib/ruby/2.4.0/rubygems/core_ext/kernel_require.rb:68:in `require'
    from /home/paul/pmds/websites/listingpros/washingtonlistingpros/bin/spring:15:in `<top (required)>'
    from bin/rails:3:in `load'
    from bin/rails:3:in `<main>'

Sigh, so much going on here. If you put a project up on github that reproduces this I can take a look.

I added you as a collaborator.

Rails 5.1 removed ActionDispatch::Callbacks#to_prepare (see https://github.com/rails/rails/commit/3f2b7d60a52ffb2ad2d4fcf889c06b631db1946b); so the issue lies in your reload_api.rb initializer. Replacing it with ActiveSupport::Reloader.to_prepare should fix the issue.

@rnubel PR a into @PAMulligan's project? Can I close this?

I'm at work at the moment, haven't been able to confirm the fix, but if you're certain this is the answer, close away and I'll reopen if it's still an issue.

Thank you @rnubel, that at least got the server running!

The problem seems to be in RedmineExtensions gem.

module Reloader
    def self.to_prepare(*args, &block)
      if defined? ActiveSupport::Reloader
        ActiveSupport::Reloader.to_prepare(*args, &block)
      else
        ActionDispatch::Reloader.to_prepare(*args, &block)
      end
    end
...
end

ActiveSupport::Reloader.to_prepare(*args, &block) needs to be called.

activesupport gem installed?

I've installed gem activsupport but still get an error:

NoMethodError: undefined method `to_prepare' for ActionDispatch::Reloader:Class

after running command:

bundle exec rake redmine:plugins:migrate NAME=redmine_dmsf RAILS_ENV="production"

Was this page helpful?
0 / 5 - 0 ratings